diff --git a/flask_jwt_extended/config.py b/flask_jwt_extended/config.py index d55284b2..e2cb65e8 100644 --- a/flask_jwt_extended/config.py +++ b/flask_jwt_extended/config.py @@ -236,6 +236,8 @@ def identity_claim_key(self): def user_claims_key(self): return current_app.config['JWT_USER_CLAIMS'] -config = _Config() - + @property + def exempt_methods(self): + return {"OPTIONS"} +config = _Config() diff --git a/flask_jwt_extended/view_decorators.py b/flask_jwt_extended/view_decorators.py index 8454b13a..fa86829b 100644 --- a/flask_jwt_extended/view_decorators.py +++ b/flask_jwt_extended/view_decorators.py @@ -32,11 +32,12 @@ def jwt_required(fn): """ @wraps(fn) def wrapper(*args, **kwargs): - 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') - _load_user(jwt_data[config.identity_claim_key]) + 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') + _load_user(jwt_data[config.identity_claim_key]) return fn(*args, **kwargs) return wrapper @@ -81,19 +82,20 @@ def fresh_jwt_required(fn): """ @wraps(fn) def wrapper(*args, **kwargs): - jwt_data = _decode_jwt_from_request(request_type='access') - ctx_stack.top.jwt = jwt_data - fresh = jwt_data['fresh'] - if isinstance(fresh, bool): - if not fresh: - raise FreshTokenRequired('Fresh token required') - else: - 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') - _load_user(jwt_data[config.identity_claim_key]) + if request.method not in config.exempt_methods: + jwt_data = _decode_jwt_from_request(request_type='access') + ctx_stack.top.jwt = jwt_data + fresh = jwt_data['fresh'] + if isinstance(fresh, bool): + if not fresh: + raise FreshTokenRequired('Fresh token required') + else: + 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') + _load_user(jwt_data[config.identity_claim_key]) return fn(*args, **kwargs) return wrapper @@ -107,9 +109,10 @@ def jwt_refresh_token_required(fn): """ @wraps(fn) def wrapper(*args, **kwargs): - jwt_data = _decode_jwt_from_request(request_type='refresh') - ctx_stack.top.jwt = jwt_data - _load_user(jwt_data[config.identity_claim_key]) + if request.method not in config.exempt_methods: + jwt_data = _decode_jwt_from_request(request_type='refresh') + ctx_stack.top.jwt = jwt_data + _load_user(jwt_data[config.identity_claim_key]) return fn(*args, **kwargs) return wrapper diff --git a/tests/test_options_method.py b/tests/test_options_method.py new file mode 100644 index 00000000..2527c464 --- /dev/null +++ b/tests/test_options_method.py @@ -0,0 +1,45 @@ +from flask import Flask, Blueprint +from flask_jwt_extended import ( + JWTManager, jwt_required, fresh_jwt_required, jwt_refresh_token_required + ) +import pytest + +@pytest.fixture(scope='function') +def app(): + app = Flask(__name__) + app.config['JWT_SECRET_KEY'] = 'secret' + JWTManager(app) + + @app.route('/jwt_required', methods=["GET", "OPTIONS"]) + @jwt_required + def jwt_required_endpoint(): + return b'ok' + + @app.route('/fresh_jwt_required', methods=["GET", "OPTIONS"]) + @fresh_jwt_required + def fresh_jwt_required_endpoint(): + return b'ok' + + @app.route('/jwt_refresh_token_required', methods=["GET", "OPTIONS"]) + @jwt_refresh_token_required + def jwt_refresh_token_required_endpoint(): + return b'ok' + + + + return app + +def test_access_jwt_required_enpoint(app): + res = app.test_client().options('/jwt_required') + assert res.status_code == 200 + assert res.data == b'ok' + +def test_access_jwt_refresh_token_required_enpoint(app): + res = app.test_client().options('/jwt_refresh_token_required') + assert res.status_code == 200 + assert res.data == b'ok' + +def test_access_fresh_jwt_required_enpoint(app): + res = app.test_client().options('/fresh_jwt_required') + assert res.status_code == 200 + assert res.data == b'ok'