Skip to content

Commit 8bacc93

Browse files
dunkmann00vimalloc
authored andcommitted
Added support for access token freshness date.
1 parent 92de911 commit 8bacc93

File tree

4 files changed

+29
-4
lines changed

4 files changed

+29
-4
lines changed

flask_jwt_extended/tokens.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import datetime
22
import uuid
33

4+
from calendar import timegm
5+
46
import jwt
57
from werkzeug.security import safe_str_cmp
68

@@ -40,7 +42,9 @@ def encode_access_token(identity, secret, algorithm, expires_delta, fresh,
4042
:param expires_delta: How far in the future this token should expire
4143
(set to False to disable expiration)
4244
:type expires_delta: datetime.timedelta or False
43-
:param fresh: If this should be a 'fresh' token or not
45+
:param fresh: If this should be a 'fresh' token or not. If a
46+
datetime.timedelta is given this will indicate how long this
47+
token will remain fresh.
4448
:param user_claims: Custom claims to include in this token. This data must
4549
be json serializable
4650
:param csrf: Whether to include a csrf double submit claim in this token
@@ -49,6 +53,11 @@ def encode_access_token(identity, secret, algorithm, expires_delta, fresh,
4953
:param user_claims_key: Which key should be used to store the user claims
5054
:return: Encoded access token
5155
"""
56+
57+
if isinstance(fresh, datetime.timedelta):
58+
now = datetime.datetime.utcnow()
59+
fresh = timegm((now + fresh).utctimetuple())
60+
5261
token_data = {
5362
identity_claim_key: identity,
5463
'fresh': fresh,

flask_jwt_extended/utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ def create_access_token(identity, fresh=False, expires_delta=None):
9898
json serializable identity out of the object.
9999
:param fresh: If this token should be marked as fresh, and can thus access
100100
:func:`~flask_jwt_extended.fresh_jwt_required` endpoints.
101-
Defaults to `False`.
101+
Defaults to `False`. This value can also be a
102+
`datetime.timedelta` in which case it will indicate how long
103+
this token will be considered fresh.
102104
:param expires_delta: A `datetime.timedelta` for how long this token should
103105
last before it expires. Set to False to disable
104106
expiration. If this is None, it will use the

flask_jwt_extended/view_decorators.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from functools import wraps
2+
from datetime import datetime
3+
from calendar import timegm
24

35
from flask import request
46
try:
@@ -81,8 +83,14 @@ def fresh_jwt_required(fn):
8183
def wrapper(*args, **kwargs):
8284
jwt_data = _decode_jwt_from_request(request_type='access')
8385
ctx_stack.top.jwt = jwt_data
84-
if not jwt_data['fresh']:
85-
raise FreshTokenRequired('Fresh token required')
86+
fresh = jwt_data['fresh']
87+
if isinstance(fresh, bool):
88+
if not fresh:
89+
raise FreshTokenRequired('Fresh token required')
90+
else:
91+
now = timegm(datetime.utcnow().utctimetuple())
92+
if fresh < now:
93+
raise FreshTokenRequired('Fresh token required')
8694
if not verify_token_claims(jwt_data[config.user_claims_key]):
8795
raise UserClaimsVerificationError('User claims verification failed')
8896
_load_user(jwt_data[config.identity_claim_key])

tests/test_view_decorators.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ def test_fresh_jwt_required(app):
7878
with app.test_request_context():
7979
access_token = create_access_token('username')
8080
fresh_access_token = create_access_token('username', fresh=True)
81+
fresh_timed_access_token = create_access_token('username', fresh=timedelta(minutes=-1))
8182
refresh_token = create_refresh_token('username')
8283

8384
response = test_client.get(url, headers=make_headers(fresh_access_token))
@@ -90,6 +91,11 @@ def test_fresh_jwt_required(app):
9091
assert response.status_code == 401
9192
assert json_data == {'msg': 'Fresh token required'}
9293

94+
response = test_client.get(url, headers=make_headers(fresh_timed_access_token))
95+
json_data = json.loads(response.get_data(as_text=True))
96+
assert response.status_code == 401
97+
assert json_data == {'msg': 'Fresh token required'}
98+
9399
response = test_client.get(url, headers=None)
94100
json_data = json.loads(response.get_data(as_text=True))
95101
assert response.status_code == 401

0 commit comments

Comments
 (0)