Skip to content

Commit 85380f0

Browse files
authored
Merge pull request #124 from decaz/master
Don't set PROPAGATE_EXCEPTIONS config setting
2 parents b6183b8 + 992dc37 commit 85380f0

File tree

8 files changed

+60
-53
lines changed

8 files changed

+60
-53
lines changed

flask_jwt_extended/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
unset_jwt_cookies, get_raw_jwt, get_current_user, current_user,
99
get_jti, decode_token, get_csrf_token
1010
)
11+
12+
__version__ = '3.7.0'

flask_jwt_extended/jwt_manager.py

-4
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ def init_app(self, app):
7474
self._set_default_configuration_options(app)
7575
self._set_error_handler_callbacks(app)
7676

77-
# Set propagate exceptions, so all of our error handlers properly
78-
# work in production
79-
app.config['PROPAGATE_EXCEPTIONS'] = True
80-
8177
def _set_error_handler_callbacks(self, app):
8278
"""
8379
Sets the error handler callbacks used by this extension

flask_jwt_extended/utils.py

+27-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from flask import _request_ctx_stack as ctx_stack
88

99
from flask_jwt_extended.config import config
10+
from flask_jwt_extended.exceptions import (
11+
RevokedTokenError, UserClaimsVerificationError, WrongTokenError
12+
)
1013
from flask_jwt_extended.tokens import decode_jwt
1114

1215

@@ -153,9 +156,31 @@ def token_in_blacklist(*args, **kwargs):
153156
return jwt_manager._token_in_blacklist_callback(*args, **kwargs)
154157

155158

156-
def verify_token_claims(*args, **kwargs):
159+
def verify_token_type(decoded_token, expected_type):
160+
if decoded_token['type'] != expected_type:
161+
raise WrongTokenError('Only {} tokens are allowed'.format(expected_type))
162+
163+
164+
def verify_token_not_blacklisted(decoded_token, request_type):
165+
if not config.blacklist_enabled:
166+
return
167+
if not has_token_in_blacklist_callback():
168+
raise RuntimeError("A token_in_blacklist_callback must be provided via "
169+
"the '@token_in_blacklist_loader' if "
170+
"JWT_BLACKLIST_ENABLED is True")
171+
if config.blacklist_access_tokens and request_type == 'access':
172+
if token_in_blacklist(decoded_token):
173+
raise RevokedTokenError('Token has been revoked')
174+
if config.blacklist_refresh_tokens and request_type == 'refresh':
175+
if token_in_blacklist(decoded_token):
176+
raise RevokedTokenError('Token has been revoked')
177+
178+
179+
def verify_token_claims(jwt_data):
157180
jwt_manager = _get_jwt_manager()
158-
return jwt_manager._claims_verification_callback(*args, **kwargs)
181+
user_claims = jwt_data[config.user_claims_key]
182+
if not jwt_manager._claims_verification_callback(user_claims):
183+
raise UserClaimsVerificationError('User claims verification failed')
159184

160185

161186
def get_csrf_token(encoded_token):

flask_jwt_extended/view_decorators.py

+9-30
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@
1010

1111
from flask_jwt_extended.config import config
1212
from flask_jwt_extended.exceptions import (
13-
InvalidHeaderError, NoAuthorizationError, WrongTokenError,
14-
FreshTokenRequired, CSRFError, UserLoadError, RevokedTokenError,
15-
UserClaimsVerificationError
13+
CSRFError, FreshTokenRequired, InvalidHeaderError, NoAuthorizationError,
14+
UserLoadError
1615
)
1716
from flask_jwt_extended.utils import (
18-
has_user_loader, user_loader, token_in_blacklist, decode_token,
19-
has_token_in_blacklist_callback, verify_token_claims
17+
decode_token, has_user_loader, user_loader, verify_token_claims,
18+
verify_token_not_blacklisted, verify_token_type
2019
)
2120

2221

@@ -35,8 +34,7 @@ def wrapper(*args, **kwargs):
3534
if request.method not in config.exempt_methods:
3635
jwt_data = _decode_jwt_from_request(request_type='access')
3736
ctx_stack.top.jwt = jwt_data
38-
if not verify_token_claims(jwt_data[config.user_claims_key]):
39-
raise UserClaimsVerificationError('User claims verification failed')
37+
verify_token_claims(jwt_data)
4038
_load_user(jwt_data[config.identity_claim_key])
4139
return fn(*args, **kwargs)
4240
return wrapper
@@ -61,8 +59,7 @@ def wrapper(*args, **kwargs):
6159
try:
6260
jwt_data = _decode_jwt_from_request(request_type='access')
6361
ctx_stack.top.jwt = jwt_data
64-
if not verify_token_claims(jwt_data[config.user_claims_key]):
65-
raise UserClaimsVerificationError('User claims verification failed')
62+
verify_token_claims(jwt_data)
6663
_load_user(jwt_data[config.identity_claim_key])
6764
except (NoAuthorizationError, InvalidHeaderError):
6865
pass
@@ -93,8 +90,7 @@ def wrapper(*args, **kwargs):
9390
now = timegm(datetime.utcnow().utctimetuple())
9491
if fresh < now:
9592
raise FreshTokenRequired('Fresh token required')
96-
if not verify_token_claims(jwt_data[config.user_claims_key]):
97-
raise UserClaimsVerificationError('User claims verification failed')
93+
verify_token_claims(jwt_data)
9894
_load_user(jwt_data[config.identity_claim_key])
9995
return fn(*args, **kwargs)
10096
return wrapper
@@ -126,21 +122,6 @@ def _load_user(identity):
126122
ctx_stack.top.jwt_user = user
127123

128124

129-
def _token_blacklisted(decoded_token, request_type):
130-
if not config.blacklist_enabled:
131-
return False
132-
if not has_token_in_blacklist_callback():
133-
raise RuntimeError("A token_in_blacklist_callback must be provided via "
134-
"the '@token_in_blacklist_loader' if "
135-
"JWT_BLACKLIST_ENABLED is True")
136-
137-
if config.blacklist_access_tokens and request_type == 'access':
138-
return token_in_blacklist(decoded_token)
139-
if config.blacklist_refresh_tokens and request_type == 'refresh':
140-
return token_in_blacklist(decoded_token)
141-
return False
142-
143-
144125
def _decode_jwt_from_headers():
145126
header_name = config.header_name
146127
header_type = config.header_type
@@ -207,11 +188,9 @@ def _decode_jwt_from_request(request_type):
207188
decoded_token = _decode_jwt_from_cookies(request_type)
208189

209190
# Make sure the type of token we received matches the request type we expect
210-
if decoded_token['type'] != request_type:
211-
raise WrongTokenError('Only {} tokens can access this endpoint'.format(request_type))
191+
verify_token_type(decoded_token, expected_type=request_type)
212192

213193
# If blacklisting is enabled, see if this token has been revoked
214-
if _token_blacklisted(decoded_token, request_type):
215-
raise RevokedTokenError('Token has been revoked')
194+
verify_token_not_blacklisted(decoded_token, request_type)
216195

217196
return decoded_token

setup.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
"""
22
Flask-JWT-Extended
3-
-------------------
3+
------------------
44
Flask-Login provides jwt endpoint protection for Flask.
55
"""
6+
import io
7+
import re
68
from setuptools import setup
79

10+
with io.open('flask_jwt_extended/__init__.py', encoding='utf-8') as f:
11+
version = re.search(r"__version__ = '(.+)'", f.read()).group(1)
12+
813
setup(name='Flask-JWT-Extended',
9-
version='3.7.0',
14+
version=version,
1015
url='https://github.com/vimalloc/flask-jwt-extended',
1116
license='MIT',
1217
author='Landon Gilbert-Bland',
@@ -18,7 +23,7 @@
1823
zip_safe=False,
1924
platforms='any',
2025
install_requires=[
21-
'Werkzeug>=0.14', # needed for samestie cookie functionality
26+
'Werkzeug>=0.14', # Needed for SameSite cookie functionality
2227
'Flask',
2328
'PyJWT',
2429
],

tests/test_blacklist.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ def test_no_blacklist_callback_method_provided(app):
111111
with app.test_request_context():
112112
access_token = create_access_token('username')
113113

114-
with pytest.raises(RuntimeError):
115-
test_client = app.test_client()
116-
test_client.get('/protected', headers=make_headers(access_token))
114+
test_client = app.test_client()
115+
response = test_client.get('/protected', headers=make_headers(access_token))
116+
assert response.status_code == 500
117117

118118

119119
def test_revoked_token_of_different_type(app):

tests/test_cookies.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ def test_setting_cookies_wihout_cookies_enabled(app):
217217
app.config['JWT_TOKEN_LOCATION'] = ['headers']
218218
test_client = app.test_client()
219219

220-
with pytest.raises(RuntimeWarning):
221-
test_client.get('/access_token')
222-
with pytest.raises(RuntimeWarning):
223-
test_client.get('/refresh_token')
224-
with pytest.raises(RuntimeWarning):
225-
test_client.get('/delete_tokens')
220+
response = test_client.get('/access_token')
221+
assert response.status_code == 500
222+
response = test_client.get('/refresh_token')
223+
assert response.status_code == 500
224+
response = test_client.get('/delete_tokens')
225+
assert response.status_code == 500
226226

227227

228228
def test_default_cookie_options(app):

tests/test_view_decorators.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_jwt_required(app):
6767
response = test_client.get(url, headers=make_headers(refresh_token))
6868
json_data = json.loads(response.get_data(as_text=True))
6969
assert response.status_code == 422
70-
assert json_data == {'msg': 'Only access tokens can access this endpoint'}
70+
assert json_data == {'msg': 'Only access tokens are allowed'}
7171

7272

7373
def test_fresh_jwt_required(app):
@@ -110,7 +110,7 @@ def test_fresh_jwt_required(app):
110110
response = test_client.get(url, headers=make_headers(refresh_token))
111111
json_data = json.loads(response.get_data(as_text=True))
112112
assert response.status_code == 422
113-
assert json_data == {'msg': 'Only access tokens can access this endpoint'}
113+
assert json_data == {'msg': 'Only access tokens are allowed'}
114114

115115
# Test with custom response
116116
@jwtM.needs_fresh_token_loader
@@ -135,12 +135,12 @@ def test_refresh_jwt_required(app):
135135
response = test_client.get(url, headers=make_headers(fresh_access_token))
136136
json_data = json.loads(response.get_data(as_text=True))
137137
assert response.status_code == 422
138-
assert json_data == {'msg': 'Only refresh tokens can access this endpoint'}
138+
assert json_data == {'msg': 'Only refresh tokens are allowed'}
139139

140140
response = test_client.get(url, headers=make_headers(access_token))
141141
json_data = json.loads(response.get_data(as_text=True))
142142
assert response.status_code == 422
143-
assert json_data == {'msg': 'Only refresh tokens can access this endpoint'}
143+
assert json_data == {'msg': 'Only refresh tokens are allowed'}
144144

145145
response = test_client.get(url, headers=None)
146146
json_data = json.loads(response.get_data(as_text=True))
@@ -176,7 +176,7 @@ def test_jwt_optional(app):
176176
response = test_client.get(url, headers=make_headers(refresh_token))
177177
json_data = json.loads(response.get_data(as_text=True))
178178
assert response.status_code == 422
179-
assert json_data == {'msg': 'Only access tokens can access this endpoint'}
179+
assert json_data == {'msg': 'Only access tokens are allowed'}
180180

181181
response = test_client.get(url, headers=None)
182182
json_data = json.loads(response.get_data(as_text=True))

0 commit comments

Comments
 (0)