Skip to content

Commit b3e3798

Browse files
committed
Working on the docs
1 parent 01603bc commit b3e3798

15 files changed

+132
-326
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "docs/_themes"]
2+
path = docs/_themes
3+
url = https://github.com/pallets/flask-sphinx-themes.git

docs/_themes

Submodule _themes added at d5b6570

docs/add_custom_data_claims.rst

Lines changed: 13 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,16 @@
11
Adding Custom Data (Claims) to the Access Token
22
===============================================
33

4-
You may want to store additional information in the access token. Perhaps you want to save the access roles this user has so you can access them in the view functions (without having to make a database call each time). This can be done with the user_claims_loader decorator, and accessed later with the 'get_jwt_claims()' method (in a protected endpoint).
5-
6-
7-
.. code-block:: python
8-
9-
from flask import Flask, jsonify, request
10-
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, \
11-
get_jwt_claims
12-
13-
app = Flask(__name__)
14-
app.secret_key = 'super-secret' # Change this!
15-
jwt = JWTManager(app)
16-
17-
18-
# Using the user_claims_loader, we can specify a method that will be called
19-
# when creating access tokens, and add these claims to the said token. This
20-
# method is passed the identity of who the token is being created for, and
21-
# must return data that is json serializable
22-
@jwt.user_claims_loader
23-
def add_claims_to_access_token(identity):
24-
return {
25-
'hello': identity,
26-
'foo': ['bar', 'baz']
27-
}
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 = {'access_token': create_access_token(username)}
38-
return jsonify(ret), 200
39-
40-
41-
# In a protected view, get the claims you added to the jwt with the
42-
# get_jwt_claims() method
43-
@app.route('/protected', methods=['GET'])
44-
@jwt_required
45-
def protected():
46-
claims = get_jwt_claims()
47-
return jsonify({
48-
'hello_is': claims['hello'],
49-
'foo_is': claims['foo']
50-
}), 200
51-
52-
if __name__ == '__main__':
53-
app.run()
4+
You may want to store additional information in the access token. Perhaps you
5+
want to save the permissions this user has so you can access them in the view
6+
functions, without having to make a database call each time. This can be done
7+
with the user_claims_loader decorator, and accessed later with the
8+
'get_jwt_claims()' method (in a protected endpoint).
9+
10+
.. literalinclude:: ../examples/additional_data_in_access_token.py
11+
12+
Storing data in an access token can be good for performance. If you store data
13+
in the token, you wont need to look it up from disk next time you need it in
14+
a protected endpoint. But be warned, any data in the access token can be easily
15+
viewed with anyone who has access to said token, so refrain from storing
16+
critical data there!

docs/basic_usage.rst

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,10 @@ Basic Usage
55
In its simplest form, there is not much to using flask_jwt_extended.
66

77

8-
.. code-block :: python
9-
10-
from flask import Flask, jsonify, request
11-
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
12-
13-
app = Flask(__name__)
14-
app.secret_key = 'super-secret' # Change this!
15-
16-
# Setup the Flask-JWT-Extended extension
17-
jwt = JWTManager(app)
18-
19-
20-
# Provide a method to create access tokens. The create_access_token() function
21-
# is used to actually generate the token
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-
# Protect a view with jwt_required, which requires a valid access token in the
34-
# request to access.
35-
@app.route('/protected', methods=['GET'])
36-
@jwt_required
37-
def protected():
38-
return jsonify({'hello': 'world'}), 200
39-
40-
if __name__ == '__main__':
41-
app.run()
42-
8+
.. literalinclude:: ../examples/simple.py
439

4410
To access a jwt_required protected view, all we have to do is send an authorization head with the request that include the token. The header looks like this:
4511

46-
4712
.. code-block :: bash
4813
4914
Authorization: Bearer <access_token>
@@ -53,22 +18,20 @@ We can see this in action using CURL:
5318

5419
.. code-block :: bash
5520
56-
$ curl --write-out "%{http_code}\n" http://localhost:5000/protected
21+
$ curl http://localhost:5000/protected
5722
{
5823
"msg": "Missing Authorization Header"
5924
}
60-
401
6125
62-
$ curl --write-out "%{http_code}\n" -H "Content-Type: application/json" -X POST -d '{"username":"test","password":"test"}' http://localhost:5000/login
26+
$ curl -H "Content-Type: application/json" -X POST \
27+
-d '{"username":"test","password":"test"}' http://localhost:5000/login
6328
{
6429
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6dHJ1ZSwianRpIjoiZjhmNDlmMjUtNTQ4OS00NmRjLTkyOWUtZTU2Y2QxOGZhNzRlIiwidXNlcl9jbGFpbXMiOnt9LCJuYmYiOjE0NzQ0NzQ3OTEsImlhdCI6MTQ3NDQ3NDc5MSwiaWRlbnRpdHkiOiJ0ZXN0IiwiZXhwIjoxNDc0NDc1NjkxLCJ0eXBlIjoiYWNjZXNzIn0.vCy0Sec61i9prcGIRRCbG8e9NV6_wFH2ICFgUGCLKpc"
6530
}
66-
200
6731
6832
$ export ACCESS="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6dHJ1ZSwianRpIjoiZjhmNDlmMjUtNTQ4OS00NmRjLTkyOWUtZTU2Y2QxOGZhNzRlIiwidXNlcl9jbGFpbXMiOnt9LCJuYmYiOjE0NzQ0NzQ3OTEsImlhdCI6MTQ3NDQ3NDc5MSwiaWRlbnRpdHkiOiJ0ZXN0IiwiZXhwIjoxNDc0NDc1NjkxLCJ0eXBlIjoiYWNjZXNzIn0.vCy0Sec61i9prcGIRRCbG8e9NV6_wFH2ICFgUGCLKpc"
6933
70-
$ curl --write-out "%{http_code}\n" -H "Authorization: Bearer $ACCESS" http://localhost:5000/protected
34+
$ curl -H "Authorization: Bearer $ACCESS" http://localhost:5000/protected
7135
{
7236
"hello": "world"
7337
}
74-
200

docs/changing_default_behavior.rst

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,36 @@
11
Changing Default Behaviors
22
==========================
33

4-
5-
We provide what we think are sensible behaviors when attempting to access a protected endpoint. If the access token is not valid for any reason (missing, expired, tampered with, etc) we will return json in the format of {'msg': 'why accessing endpoint failed'} along with an appropriate http status code (generally 401 or 422). However, you may want to customize what you returned in these situations. We can do that with the jwt_manager _loader functions.
6-
7-
8-
.. code-block:: python
9-
10-
from flask import Flask, jsonify, request
11-
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
12-
13-
app = Flask(__name__)
14-
app.secret_key = 'super-secret' # Change this!
15-
jwt = JWTManager(app)
16-
17-
18-
# Use the expired_token_loader to call this function whenever an expired but
19-
# otherwise valid access token tries to access an endpoint
20-
@jwt.expired_token_loader
21-
def my_expired_token_callback():
22-
return jsonify({
23-
'status': 401,
24-
'sub_status': 101,
25-
'msg': 'The token has expired'
26-
}), 200
27-
28-
29-
@app.route('/login', methods=['POST'])
30-
def login():
31-
username = request.json.get('username', None)
32-
password = request.json.get('password', None)
33-
if username != 'test' and password != 'test':
34-
return jsonify({"msg": "Bad username or password"}), 401
35-
36-
ret = {'access_token': create_access_token(username)}
37-
return jsonify(ret), 200
38-
39-
40-
@app.route('/protected', methods=['GET'])
41-
@jwt_required
42-
def protected():
43-
return jsonify({'hello': 'world'}), 200
44-
45-
if __name__ == '__main__':
46-
app.run()
47-
48-
49-
50-
************************************
51-
Loader functions are:
52-
************************************
53-
54-
.. autoclass:: flask_jwt_extended.jwt_manager.JWTManager
55-
:members:
56-
..
57-
.. .. literalinclude:: ../flask_jwt_extended/jwt_manager.py
58-
.. :language: python
59-
.. :emphasize-lines: 60-122
60-
.. :linenos:
4+
We provide what we think are sensible behaviors when attempting to access a
5+
protected endpoint. If the access token is not valid for any reason (missing,
6+
expired, tampered with, etc) we will return json in the format of {'msg': 'why
7+
accessing endpoint failed'} along with an appropriate http status code
8+
(generally 401 or 422). However, you may want to customize what you returned in
9+
these situations. We can do that with the jwt_manager loader functions.
10+
11+
12+
.. literalinclude:: ../examples/loaders.py
13+
14+
Possible loader functions are:
15+
16+
.. list-table::
17+
:header-rows: 1
18+
19+
* - Decorator
20+
- Description
21+
- Callback Function Arguments
22+
* - expired_token_loader
23+
- Function to call when an expired token accesses a protected view
24+
- None
25+
* - invalid_token_loader
26+
- Function to call when an invalid token accesses a protected view
27+
- One argument: error string of why it is invalid
28+
* - unauthorized_loader
29+
- Function to call when a request with no JWT accesses a protected view
30+
- None
31+
* - needs_fresh_token_loader
32+
- Function to call when a non-fresh token tries to access a **fresh_jwt_required** view
33+
- None
34+
* - revoked_token_loader
35+
- Function to call when a revoked token accesses a protected view
36+
- None

docs/conf.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# -*- coding: utf-8 -*-
22
#
3-
import sphinx_rtd_theme
43
import sys, os
54
# flask-jwt-extended documentation build configuration file, created by
65
# sphinx-quickstart on Thu Oct 6 13:07:36 2016.
@@ -20,12 +19,9 @@
2019
#
2120

2221

23-
# sys.path.insert(0, os.path.abspath('.'))
2422
sys.path.insert(0, os.path.abspath('../../..'))
2523
sys.path.insert(0, os.path.abspath('../flask_jwt_extended/'))
26-
# sys.path.insert(0, os.path.abspath('../../flask-jwt-extended/flask_jwt_extended/'))
27-
28-
print sys.path
24+
sys.path.append(os.path.join(os.path.dirname(__file__), '_themes'))
2925

3026
# -- General configuration ------------------------------------------------
3127

@@ -114,7 +110,7 @@
114110
# show_authors = False
115111

116112
# The name of the Pygments (syntax highlighting) style to use.
117-
pygments_style = 'sphinx'
113+
# pygments_style = 'sphinx'
118114

119115
# A list of ignored prefixes for module index sorting.
120116
# modindex_common_prefix = []
@@ -131,7 +127,8 @@
131127
# The theme to use for HTML and HTML Help pages. See the documentation for
132128
# a list of builtin themes.
133129
#
134-
html_theme = 'sphinx_rtd_theme'
130+
#html_theme = 'sphinx_rtd_theme'
131+
html_theme = 'flask'
135132

136133
# Theme options are theme-specific and customize the look and feel of a theme
137134
# further. For a list of options available for each theme, see the

docs/options.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Configuration Options
2-
======================
2+
=====================
33

44
.. literalinclude:: ../flask_jwt_extended/config.py
55
:language: python

docs/refresh_tokens.rst

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,12 @@
11
Refresh Tokens
22
==============
33

4-
Flask-JWT-Extended supports refresh tokens out of the box. These are longer lived token which cannot access a jwt_required protected endpoint, but can be used to create new access tokens once an old access token has expired. By setting the access tokens to a shorter lifetime (see Options below), and utilizing fresh tokens for critical views (see Fresh Tokens below) we can help reduce the damage done if an access token is stolen. Here is an example of how you might use them in your application:
4+
Flask-JWT-Extended supports refresh tokens out of the box. These are longer
5+
lived token which cannot access a jwt_required protected endpoint, but can be
6+
used to create new access tokens once an old access token has expired.
57

8+
.. literalinclude:: ../examples/refresh_tokens.py
69

7-
.. code-block:: python
8-
9-
from flask import Flask, jsonify, request
10-
from flask_jwt_extended import JWTManager, jwt_required, create_access_token, \
11-
jwt_refresh_token_required, create_refresh_token, get_jwt_identity
12-
13-
app = Flask(__name__)
14-
app.secret_key = 'super-secret' # Change this!
15-
jwt = JWTManager(app)
16-
17-
18-
@app.route('/login', methods=['POST'])
19-
def login():
20-
username = request.json.get('username', None)
21-
password = request.json.get('password', None)
22-
if username != 'test' and password != 'test':
23-
return jsonify({"msg": "Bad username or password"}), 401
24-
25-
# Use create_access_token() and create_refresh_token() to create our
26-
# access and refresh tokens
27-
ret = {
28-
'access_token': create_access_token(identity=username),
29-
'refresh_token': create_refresh_token(identity=username)
30-
}
31-
return jsonify(ret), 200
32-
33-
34-
# The jwt_refresh_token_required decorator insures a valid refresh token is
35-
# present in the request before calling this endpoint. We can use the
36-
# get_jwt_identity() function to get the identity of the refresh toke, and use
37-
# the create_access_token() function again to make a new access token for this
38-
# identity.
39-
@app.route('/refresh', methods=['POST'])
40-
@jwt_refresh_token_required
41-
def refresh():
42-
current_user = get_jwt_identity()
43-
ret = {
44-
'access_token': create_access_token(identity=current_user)
45-
}
46-
return jsonify(ret), 200
47-
48-
49-
@app.route('/protected', methods=['GET'])
50-
@jwt_required
51-
def protected():
52-
username = get_jwt_identity()
53-
return jsonify({'hello': 'from {}'.format(username)}), 200
54-
55-
if __name__ == '__main__':
56-
app.run()
10+
By setting the access tokens to a shorter lifetime (see Configuration Options),
11+
and utilizing fresh tokens for critical views (see Token Freshness next) we can
12+
help reduce the damage done if an access token is stolen.

0 commit comments

Comments
 (0)