Skip to content

Commit fe5e5bf

Browse files
committed
Ignore options also in fresh_jwt_required and
`jwt_refresh_token_required`, improve and add tests
1 parent ea5fa12 commit fe5e5bf

File tree

3 files changed

+56
-37
lines changed

3 files changed

+56
-37
lines changed

flask_jwt_extended/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,6 @@ def user_claims_key(self):
238238

239239
@property
240240
def exempt_methods(self):
241-
return set(["OPTIONS"])
241+
return {"OPTIONS"}
242242

243243
config = _Config()

flask_jwt_extended/view_decorators.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def wrapper(*args, **kwargs):
3838
if not verify_token_claims(jwt_data[config.user_claims_key]):
3939
raise UserClaimsVerificationError('User claims verification failed')
4040
_load_user(jwt_data[config.identity_claim_key])
41-
return fn(*args, **kwargs)
41+
return fn(*args, **kwargs)
4242
return wrapper
4343

4444

@@ -82,19 +82,20 @@ def fresh_jwt_required(fn):
8282
"""
8383
@wraps(fn)
8484
def wrapper(*args, **kwargs):
85-
jwt_data = _decode_jwt_from_request(request_type='access')
86-
ctx_stack.top.jwt = jwt_data
87-
fresh = jwt_data['fresh']
88-
if isinstance(fresh, bool):
89-
if not fresh:
90-
raise FreshTokenRequired('Fresh token required')
91-
else:
92-
now = timegm(datetime.utcnow().utctimetuple())
93-
if fresh < now:
94-
raise FreshTokenRequired('Fresh token required')
95-
if not verify_token_claims(jwt_data[config.user_claims_key]):
96-
raise UserClaimsVerificationError('User claims verification failed')
97-
_load_user(jwt_data[config.identity_claim_key])
85+
if request.method not in config.exempt_methods:
86+
jwt_data = _decode_jwt_from_request(request_type='access')
87+
ctx_stack.top.jwt = jwt_data
88+
fresh = jwt_data['fresh']
89+
if isinstance(fresh, bool):
90+
if not fresh:
91+
raise FreshTokenRequired('Fresh token required')
92+
else:
93+
now = timegm(datetime.utcnow().utctimetuple())
94+
if fresh < now:
95+
raise FreshTokenRequired('Fresh token required')
96+
if not verify_token_claims(jwt_data[config.user_claims_key]):
97+
raise UserClaimsVerificationError('User claims verification failed')
98+
_load_user(jwt_data[config.identity_claim_key])
9899
return fn(*args, **kwargs)
99100
return wrapper
100101

@@ -108,9 +109,10 @@ def jwt_refresh_token_required(fn):
108109
"""
109110
@wraps(fn)
110111
def wrapper(*args, **kwargs):
111-
jwt_data = _decode_jwt_from_request(request_type='refresh')
112-
ctx_stack.top.jwt = jwt_data
113-
_load_user(jwt_data[config.identity_claim_key])
112+
if request.method not in config.exempt_methods:
113+
jwt_data = _decode_jwt_from_request(request_type='refresh')
114+
ctx_stack.top.jwt = jwt_data
115+
_load_user(jwt_data[config.identity_claim_key])
114116
return fn(*args, **kwargs)
115117
return wrapper
116118

tests/test_options_method.py

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from flask import Flask, Blueprint
2-
from flask_jwt_extended import JWTManager, jwt_required, create_access_token
2+
from flask_jwt_extended import (
3+
JWTManager, jwt_required, fresh_jwt_required, jwt_refresh_token_required
4+
)
35
import pytest
46

57
@pytest.fixture(scope='function')
@@ -8,27 +10,42 @@ def app():
810
app.config['JWT_SECRET_KEY'] = 'secret'
911
JWTManager(app)
1012

11-
protected_bp = Blueprint('protected', __name__)
12-
13-
# This protects the entire blueprint,
14-
# Also the OPTIONS method
15-
@protected_bp.before_request
13+
@app.route('/jwt_required', methods=["GET", "OPTIONS"])
1614
@jwt_required
17-
def protect():
18-
pass
15+
def jwt_required_endpoint():
16+
return b'ok'
17+
18+
@app.route('/fresh_jwt_required', methods=["GET", "OPTIONS"])
19+
@fresh_jwt_required
20+
def fresh_jwt_required_endpoint():
21+
return b'ok'
22+
23+
@app.route('/jwt_refresh_token_required', methods=["GET", "OPTIONS"])
24+
@jwt_refresh_token_required
25+
def jwt_refresh_token_required_endpoint():
26+
return b'ok'
27+
1928

20-
@protected_bp.route('/protected', methods=["GET"])
21-
@jwt_required
22-
def protected():
23-
return 'ok'
2429

25-
app.register_blueprint(protected_bp)
2630
return app
2731

28-
def test_access_protected_enpoint(app):
29-
client = app.test_client()
30-
assert client.get('/protected').status_code == 401 # ok
32+
def test_access_jwt_required_enpoint(app):
33+
# Test the options method shoud not be
34+
# affected by jwt required
35+
res = app.test_client().options('/jwt_required')
36+
assert res.status_code == 200
37+
assert res.data == b'ok'
38+
39+
def test_access_jwt_refresh_token_required_enpoint(app):
40+
# Test the options method shoud not be
41+
# affected by jwt required
42+
res = app.test_client().options('/jwt_refresh_token_required')
43+
assert res.status_code == 200
44+
assert res.data == b'ok'
3145

32-
def test_access_protected_enpoint_options(app):
33-
client = app.test_client()
34-
assert client.options('/protected').status_code == 200 # test fails
46+
def test_access_fresh_jwt_required_enpoint(app):
47+
# Test the options method shoud not be
48+
# affected by jwt required
49+
res = app.test_client().options('/fresh_jwt_required')
50+
assert res.status_code == 200
51+
assert res.data == b'ok'

0 commit comments

Comments
 (0)