1
1
JWT Locations
2
2
=============
3
- JWTs can be passed sent in many different ways to a protected route. These
4
- available ways the tokens can be passed in can be controlled globally via
5
- the ` app.config["JWT_TOKEN_LOCATION'] ` option, or overridden on a per route
6
- basis via the `locations ` argument in :func: ` ~flask_jwt_extended.jwt_required `.
7
- Lets see how working with different locations look like in javascript:
3
+ JWTs can be sent in with a request in many different ways. You can control which
4
+ ways you want to accept JWTs in your Flask application via the ` JWT_TOKEN_LOCATION `
5
+ :ref: ` configuration option<Configuration Options> `. You can also override that global
6
+ configuration on a per route basis via the `locations ` argument in
7
+ :func: ` ~flask_jwt_extended.jwt_required `.
8
8
9
9
.. literalinclude :: ../examples/jwt_locations.py
10
10
11
+ Lets take a look at how you could utilize all of these locations using some
12
+ javascript in a web browser.
13
+
11
14
Headers
12
15
~~~~~~~
13
16
Working JWTs via headers is a pretty simple process. All you need to do is store
@@ -44,30 +47,40 @@ Cookies
44
47
Cookies are a fantastic way of handling JWTs if you are using a web browser.
45
48
They offer some nice benefits compared to the headers approach:
46
49
47
- * They can be set to send only if you are on an HTTPS connection . This prevents a
48
- JWT from accidentally being leaked by being sent over an unsecure connection.
50
+ * They can be configured to send only over HTTPS. This prevents a JWT from
51
+ accidentally being sent, and possibly compromised, over an unsecure connection.
49
52
* They are stored in an http-only cookie, which prevents XSS attacks from being
50
53
able to steal the underlying JWT.
51
- * You flask application can implicitly refresh JWTs that are close to expiring,
54
+ * You Flask application can implicitly refresh JWTs that are close to expiring,
52
55
which simplifies the logic of keeping active users logged in. More on this in
53
56
the next section!
54
57
55
58
Of course, when using cookies you also need to do some additional work to prevent
56
- Cross Site Request Forgery (CSRF) attacks. In this extension we do this by utilizing
57
- the double submit verification method. The basic idea behind this is that we are
58
- going to save two cookies when logging in. The first cookie contains the access
59
- token, and encoded in the access token is double submit token. This cookie is
60
- set as http-only, so javascript cannot access the cookie to decode the double
61
- submit token. The second cookie we save contains only the same double submit
62
- token, but this time in a cookie that is readable by javascript. Whenever a
63
- request is made, it needs to include an `X-CSRF-TOKEN ` header, with the value
64
- of the double submit token. If the value in this header does not match the value
65
- stored in the access token, the request is kicked out as invalid. This prevents
66
- any CSRF attacks, because although they can implictitly send in the JWT as part
67
- of the request, they have no way to also include the double submit token.
59
+ Cross Site Request Forgery (CSRF) attacks. In this extension we handle this via
60
+ something called double submit verification.
61
+
62
+ The basic idea behind double submit verification is that a JWT coming from a
63
+ cookie will only be considered valid if a special double submit token is also
64
+ present in the request, and that double submit token must not be something that
65
+ is automatically sent by a web browser (ie it cannot be another cookie).
66
+
67
+ By default, we accomplish this by setting two cookies when someone logging in.
68
+ The first cookie contains the JWT, and encoded in that JWT is the double submit
69
+ token. This cookie is set as http-only, so that it cannot be access via javascript
70
+ (this is what prevents XSS attacks from being able to steal the JWT). The second
71
+ cookie we set contains only the same double submit token, but this time in a
72
+ cookie that is readable by javascript. Whenever a request is made, it needs to
73
+ include an `X-CSRF-TOKEN ` header, with the value of the double submit token.
74
+ If the value in this header does not match the value stored in the JWT, the
75
+ request is kicked out as invalid.
76
+
77
+ Because the double submit token needs to be present as a header (which wont be
78
+ automatically sent on a request), and some malicious javascript running on a
79
+ different domain will not be able to read the cookie containing the double submit
80
+ token on your website, we have successfully thwarted any CSRF attacks.
68
81
69
82
This does mean that whenever you are making a request, you need to manually
70
- include the double submit token header, otherwise your requests will be kicked
83
+ include the ` X-CSRF-TOKEN ` header, otherwise your requests will be kicked
71
84
out as invalid too. Lets look at how to do that:
72
85
73
86
.. code-block :: javascript
@@ -98,6 +111,11 @@ out as invalid too. Lets look at how to do that:
98
111
return result;
99
112
}
100
113
114
+ Note that there are additional CSRF options, such as looking for the double
115
+ submit token in a form, changing cookie paths, etc, that can be used to
116
+ tailor things to the needs of your application. See
117
+ :ref: `Cross Site Request Forgery Options ` for details.
118
+
101
119
102
120
Query String
103
121
~~~~~~~~~~~~~
@@ -122,7 +140,8 @@ in this extension.
122
140
}
123
141
124
142
async function makeRequestWithJWT() {
125
- const response = await fetch('/protected', {method: 'post'});
143
+ const jwt = localStorage.getItem('jwt')
144
+ const response = await fetch(`/protected?jwt=${jwt}`, {method: 'post'});
126
145
const result = await response.json();
127
146
return result;
128
147
}
@@ -164,7 +183,3 @@ we include the option for it regardless.
164
183
const result = await response.json();
165
184
return result;
166
185
}
167
-
168
-
169
- Overwriting Locations On a Per Route Basis
170
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 commit comments