Skip to content

Commit d1380fb

Browse files
committed
Allow more data structures for JWT_TOKEN_LOCATION & JWT_BLACKLIST_TOKEN_CHECKS
1 parent 5dd816c commit d1380fb

File tree

3 files changed

+77
-31
lines changed

3 files changed

+77
-31
lines changed

flask_jwt_extended/config.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,12 @@ def decode_key(self):
4242
@property
4343
def token_location(self):
4444
locations = current_app.config['JWT_TOKEN_LOCATION']
45-
if not isinstance(locations, list):
46-
locations = [locations]
47-
if not locations:
45+
if isinstance(locations, str):
46+
locations = (locations,)
47+
elif not isinstance(locations, (tuple, list, frozenset, set)):
48+
raise RuntimeError('JWT_TOKEN_LOCATION must be a tuple, a list, a frozenset '
49+
'or a set')
50+
elif not locations:
4851
raise RuntimeError('JWT_TOKEN_LOCATION must contain at least one '
4952
'of "headers", "cookies", "query_string", or "json"')
5053
for location in locations:
@@ -202,8 +205,11 @@ def blacklist_enabled(self):
202205
@property
203206
def blacklist_checks(self):
204207
check_type = current_app.config['JWT_BLACKLIST_TOKEN_CHECKS']
205-
if not isinstance(check_type, list):
206-
check_type = [check_type]
208+
if isinstance(check_type, str):
209+
check_type = (check_type,)
210+
elif not isinstance(check_type, (tuple, list, frozenset, set)):
211+
raise RuntimeError('JWT_BLACKLIST_TOKEN_CHECKS must be a tuple, a list, a '
212+
'frozenset or a set')
207213
for item in check_type:
208214
if item not in ('access', 'refresh'):
209215
err = 'JWT_BLACKLIST_TOKEN_CHECKS must be "access" or "refresh"'

flask_jwt_extended/jwt_manager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def _set_default_configuration_options(app):
138138
Sets the default configuration options used by this extension
139139
"""
140140
# Where to look for the JWT. Available options are cookies or headers
141-
app.config.setdefault('JWT_TOKEN_LOCATION', ['headers'])
141+
app.config.setdefault('JWT_TOKEN_LOCATION', ('headers',))
142142

143143
# Options for JWTs when the TOKEN_LOCATION is headers
144144
app.config.setdefault('JWT_HEADER_NAME', 'Authorization')
@@ -192,7 +192,7 @@ def _set_default_configuration_options(app):
192192

193193
# Options for blacklisting/revoking tokens
194194
app.config.setdefault('JWT_BLACKLIST_ENABLED', False)
195-
app.config.setdefault('JWT_BLACKLIST_TOKEN_CHECKS', ['access', 'refresh'])
195+
app.config.setdefault('JWT_BLACKLIST_TOKEN_CHECKS', ('access', 'refresh'))
196196

197197
app.config.setdefault('JWT_IDENTITY_CLAIM', 'identity')
198198
app.config.setdefault('JWT_USER_CLAIMS', 'user_claims')

tests/test_config.py

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def app():
1818

1919
def test_default_configs(app):
2020
with app.test_request_context():
21-
assert config.token_location == ['headers']
21+
assert config.token_location == ('headers',)
2222
assert config.jwt_in_query_string is False
2323
assert config.jwt_in_cookies is False
2424
assert config.jwt_in_json is False
@@ -56,7 +56,7 @@ def test_default_configs(app):
5656
assert config.algorithm == 'HS256'
5757
assert config.is_asymmetric is False
5858
assert config.blacklist_enabled is False
59-
assert config.blacklist_checks == ['access', 'refresh']
59+
assert config.blacklist_checks == ('access', 'refresh')
6060
assert config.blacklist_access_tokens is True
6161
assert config.blacklist_refresh_tokens is True
6262

@@ -105,7 +105,7 @@ def test_override_configs(app):
105105
app.config['JWT_ALGORITHM'] = 'HS512'
106106

107107
app.config['JWT_BLACKLIST_ENABLED'] = True
108-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 'refresh'
108+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ('refresh',)
109109

110110
app.config['JWT_IDENTITY_CLAIM'] = 'foo'
111111
app.config['JWT_USER_CLAIMS'] = 'bar'
@@ -156,7 +156,7 @@ class CustomJSONEncoder(JSONEncoder):
156156
assert config.algorithm == 'HS512'
157157

158158
assert config.blacklist_enabled is True
159-
assert config.blacklist_checks == ['refresh']
159+
assert config.blacklist_checks == ('refresh',)
160160
assert config.blacklist_access_tokens is False
161161
assert config.blacklist_refresh_tokens is True
162162

@@ -246,6 +246,14 @@ def test_invalid_config_options(app):
246246
with pytest.raises(RuntimeError):
247247
config.token_location
248248

249+
app.config['JWT_TOKEN_LOCATION'] = 1
250+
with pytest.raises(RuntimeError):
251+
config.token_location
252+
253+
app.config['JWT_TOKEN_LOCATION'] = {'location': 'headers'}
254+
with pytest.raises(RuntimeError):
255+
config.token_location
256+
249257
app.config['JWT_TOKEN_LOCATION'] = ['headers', 'cookies', 'banana']
250258
with pytest.raises(RuntimeError):
251259
config.token_location
@@ -275,37 +283,69 @@ def test_invalid_config_options(app):
275283
with pytest.raises(RuntimeError):
276284
config.blacklist_checks
277285

286+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 1
287+
with pytest.raises(RuntimeError):
288+
config.blacklist_checks
289+
290+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = {'token_type': 'access'}
291+
with pytest.raises(RuntimeError):
292+
config.blacklist_checks
293+
278294
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'banana']
279295
with pytest.raises(RuntimeError):
280296
config.blacklist_checks
281297

282298

283299
def test_jwt_token_locations_config(app):
284300
with app.test_request_context():
285-
app.config['JWT_TOKEN_LOCATION'] = 'headers'
286-
assert config.token_location == ['headers']
287-
app.config['JWT_TOKEN_LOCATION'] = ['headers']
288-
assert config.token_location == ['headers']
289-
app.config['JWT_TOKEN_LOCATION'] = 'cookies'
290-
assert config.token_location == ['cookies']
291-
app.config['JWT_TOKEN_LOCATION'] = ['cookies']
292-
assert config.token_location == ['cookies']
293-
app.config['JWT_TOKEN_LOCATION'] = ['cookies', 'headers']
294-
assert config.token_location == ['cookies', 'headers']
301+
allowed_locations = ('headers', 'cookies', 'query_string', 'json')
302+
allowed_data_structures = (tuple, list, frozenset, set)
303+
304+
for location in allowed_locations:
305+
app.config['JWT_TOKEN_LOCATION'] = location
306+
assert config.token_location == (location,)
307+
308+
for locations in (
309+
data_structure((location,))
310+
for data_structure in allowed_data_structures
311+
for location in allowed_locations
312+
):
313+
app.config['JWT_TOKEN_LOCATION'] = locations
314+
assert config.token_location == locations
315+
316+
for locations in (
317+
data_structure(allowed_locations[:i])
318+
for data_structure in allowed_data_structures
319+
for i in range(1, len(allowed_locations))
320+
):
321+
app.config['JWT_TOKEN_LOCATION'] = locations
322+
assert config.token_location == locations
295323

296324

297325
def test_jwt_blacklist_token_checks_config(app):
298326
with app.test_request_context():
299-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 'access'
300-
assert config.blacklist_checks == ['access']
301-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access']
302-
assert config.blacklist_checks == ['access']
303-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = 'refresh'
304-
assert config.blacklist_checks == ['refresh']
305-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['refresh']
306-
assert config.blacklist_checks == ['refresh']
307-
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = ['access', 'refresh']
308-
assert config.blacklist_checks == ['access', 'refresh']
327+
allowed_token_types = ('access', 'refresh')
328+
allowed_data_structures = (tuple, list, frozenset, set)
329+
330+
for token_type in allowed_token_types:
331+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = token_type
332+
assert config.blacklist_checks == (token_type,)
333+
334+
for token_types in (
335+
data_structure((token_type,))
336+
for data_structure in allowed_data_structures
337+
for token_type in allowed_token_types
338+
):
339+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = token_types
340+
assert config.blacklist_checks == token_types
341+
342+
for token_types in (
343+
data_structure(allowed_token_types[:i])
344+
for data_structure in allowed_data_structures
345+
for i in range(1, len(allowed_token_types))
346+
):
347+
app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = token_types
348+
assert config.blacklist_checks == token_types
309349

310350

311351
def test_csrf_protect_config(app):

0 commit comments

Comments
 (0)