Skip to content

Commit

Permalink
Merge pull request #124 from decaz/master
Browse files Browse the repository at this point in the history
Don't set PROPAGATE_EXCEPTIONS config setting
  • Loading branch information
vimalloc authored Feb 22, 2018
2 parents b6183b8 + 992dc37 commit 85380f0
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 53 deletions.
2 changes: 2 additions & 0 deletions flask_jwt_extended/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
unset_jwt_cookies, get_raw_jwt, get_current_user, current_user,
get_jti, decode_token, get_csrf_token
)

__version__ = '3.7.0'
4 changes: 0 additions & 4 deletions flask_jwt_extended/jwt_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ def init_app(self, app):
self._set_default_configuration_options(app)
self._set_error_handler_callbacks(app)

# Set propagate exceptions, so all of our error handlers properly
# work in production
app.config['PROPAGATE_EXCEPTIONS'] = True

def _set_error_handler_callbacks(self, app):
"""
Sets the error handler callbacks used by this extension
Expand Down
29 changes: 27 additions & 2 deletions flask_jwt_extended/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from flask import _request_ctx_stack as ctx_stack

from flask_jwt_extended.config import config
from flask_jwt_extended.exceptions import (
RevokedTokenError, UserClaimsVerificationError, WrongTokenError
)
from flask_jwt_extended.tokens import decode_jwt


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


def verify_token_claims(*args, **kwargs):
def verify_token_type(decoded_token, expected_type):
if decoded_token['type'] != expected_type:
raise WrongTokenError('Only {} tokens are allowed'.format(expected_type))


def verify_token_not_blacklisted(decoded_token, request_type):
if not config.blacklist_enabled:
return
if not has_token_in_blacklist_callback():
raise RuntimeError("A token_in_blacklist_callback must be provided via "
"the '@token_in_blacklist_loader' if "
"JWT_BLACKLIST_ENABLED is True")
if config.blacklist_access_tokens and request_type == 'access':
if token_in_blacklist(decoded_token):
raise RevokedTokenError('Token has been revoked')
if config.blacklist_refresh_tokens and request_type == 'refresh':
if token_in_blacklist(decoded_token):
raise RevokedTokenError('Token has been revoked')


def verify_token_claims(jwt_data):
jwt_manager = _get_jwt_manager()
return jwt_manager._claims_verification_callback(*args, **kwargs)
user_claims = jwt_data[config.user_claims_key]
if not jwt_manager._claims_verification_callback(user_claims):
raise UserClaimsVerificationError('User claims verification failed')


def get_csrf_token(encoded_token):
Expand Down
39 changes: 9 additions & 30 deletions flask_jwt_extended/view_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@

from flask_jwt_extended.config import config
from flask_jwt_extended.exceptions import (
InvalidHeaderError, NoAuthorizationError, WrongTokenError,
FreshTokenRequired, CSRFError, UserLoadError, RevokedTokenError,
UserClaimsVerificationError
CSRFError, FreshTokenRequired, InvalidHeaderError, NoAuthorizationError,
UserLoadError
)
from flask_jwt_extended.utils import (
has_user_loader, user_loader, token_in_blacklist, decode_token,
has_token_in_blacklist_callback, verify_token_claims
decode_token, has_user_loader, user_loader, verify_token_claims,
verify_token_not_blacklisted, verify_token_type
)


Expand All @@ -35,8 +34,7 @@ def wrapper(*args, **kwargs):
if request.method not in config.exempt_methods:
jwt_data = _decode_jwt_from_request(request_type='access')
ctx_stack.top.jwt = jwt_data
if not verify_token_claims(jwt_data[config.user_claims_key]):
raise UserClaimsVerificationError('User claims verification failed')
verify_token_claims(jwt_data)
_load_user(jwt_data[config.identity_claim_key])
return fn(*args, **kwargs)
return wrapper
Expand All @@ -61,8 +59,7 @@ def wrapper(*args, **kwargs):
try:
jwt_data = _decode_jwt_from_request(request_type='access')
ctx_stack.top.jwt = jwt_data
if not verify_token_claims(jwt_data[config.user_claims_key]):
raise UserClaimsVerificationError('User claims verification failed')
verify_token_claims(jwt_data)
_load_user(jwt_data[config.identity_claim_key])
except (NoAuthorizationError, InvalidHeaderError):
pass
Expand Down Expand Up @@ -93,8 +90,7 @@ def wrapper(*args, **kwargs):
now = timegm(datetime.utcnow().utctimetuple())
if fresh < now:
raise FreshTokenRequired('Fresh token required')
if not verify_token_claims(jwt_data[config.user_claims_key]):
raise UserClaimsVerificationError('User claims verification failed')
verify_token_claims(jwt_data)
_load_user(jwt_data[config.identity_claim_key])
return fn(*args, **kwargs)
return wrapper
Expand Down Expand Up @@ -126,21 +122,6 @@ def _load_user(identity):
ctx_stack.top.jwt_user = user


def _token_blacklisted(decoded_token, request_type):
if not config.blacklist_enabled:
return False
if not has_token_in_blacklist_callback():
raise RuntimeError("A token_in_blacklist_callback must be provided via "
"the '@token_in_blacklist_loader' if "
"JWT_BLACKLIST_ENABLED is True")

if config.blacklist_access_tokens and request_type == 'access':
return token_in_blacklist(decoded_token)
if config.blacklist_refresh_tokens and request_type == 'refresh':
return token_in_blacklist(decoded_token)
return False


def _decode_jwt_from_headers():
header_name = config.header_name
header_type = config.header_type
Expand Down Expand Up @@ -207,11 +188,9 @@ def _decode_jwt_from_request(request_type):
decoded_token = _decode_jwt_from_cookies(request_type)

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

# If blacklisting is enabled, see if this token has been revoked
if _token_blacklisted(decoded_token, request_type):
raise RevokedTokenError('Token has been revoked')
verify_token_not_blacklisted(decoded_token, request_type)

return decoded_token
11 changes: 8 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
"""
Flask-JWT-Extended
-------------------
------------------
Flask-Login provides jwt endpoint protection for Flask.
"""
import io
import re
from setuptools import setup

with io.open('flask_jwt_extended/__init__.py', encoding='utf-8') as f:
version = re.search(r"__version__ = '(.+)'", f.read()).group(1)

setup(name='Flask-JWT-Extended',
version='3.7.0',
version=version,
url='https://github.com/vimalloc/flask-jwt-extended',
license='MIT',
author='Landon Gilbert-Bland',
Expand All @@ -18,7 +23,7 @@
zip_safe=False,
platforms='any',
install_requires=[
'Werkzeug>=0.14', # needed for samestie cookie functionality
'Werkzeug>=0.14', # Needed for SameSite cookie functionality
'Flask',
'PyJWT',
],
Expand Down
6 changes: 3 additions & 3 deletions tests/test_blacklist.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ def test_no_blacklist_callback_method_provided(app):
with app.test_request_context():
access_token = create_access_token('username')

with pytest.raises(RuntimeError):
test_client = app.test_client()
test_client.get('/protected', headers=make_headers(access_token))
test_client = app.test_client()
response = test_client.get('/protected', headers=make_headers(access_token))
assert response.status_code == 500


def test_revoked_token_of_different_type(app):
Expand Down
12 changes: 6 additions & 6 deletions tests/test_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,12 @@ def test_setting_cookies_wihout_cookies_enabled(app):
app.config['JWT_TOKEN_LOCATION'] = ['headers']
test_client = app.test_client()

with pytest.raises(RuntimeWarning):
test_client.get('/access_token')
with pytest.raises(RuntimeWarning):
test_client.get('/refresh_token')
with pytest.raises(RuntimeWarning):
test_client.get('/delete_tokens')
response = test_client.get('/access_token')
assert response.status_code == 500
response = test_client.get('/refresh_token')
assert response.status_code == 500
response = test_client.get('/delete_tokens')
assert response.status_code == 500


def test_default_cookie_options(app):
Expand Down
10 changes: 5 additions & 5 deletions tests/test_view_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_jwt_required(app):
response = test_client.get(url, headers=make_headers(refresh_token))
json_data = json.loads(response.get_data(as_text=True))
assert response.status_code == 422
assert json_data == {'msg': 'Only access tokens can access this endpoint'}
assert json_data == {'msg': 'Only access tokens are allowed'}


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

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

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

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

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

0 comments on commit 85380f0

Please sign in to comment.