Skip to content

Commit 2baf220

Browse files
committed
Do not add user_claims to access token if empty
If `user_claims` are empty dict (`{}`) or `None`, do not add them to JWT. This should result in shorter token length.
1 parent 2d866a1 commit 2baf220

File tree

2 files changed

+58
-15
lines changed

2 files changed

+58
-15
lines changed

flask_jwt_extended/tokens.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@ def encode_access_token(identity, secret, algorithm, expires_delta, fresh,
4848
identity_claim: identity,
4949
'fresh': fresh,
5050
'type': 'access',
51-
'user_claims': user_claims,
5251
}
52+
53+
# Add `user_claims` only is not empty or None.
54+
if user_claims:
55+
token_data['user_claims'] = user_claims
56+
5357
if csrf:
5458
token_data['csrf'] = _create_csrf_token()
5559
return _encode_jwt(token_data, expires_delta, secret, algorithm)
@@ -104,7 +108,7 @@ def decode_jwt(encoded_token, secret, algorithm, csrf, identity_claim):
104108
if 'fresh' not in data:
105109
raise JWTDecodeError("Missing claim: fresh")
106110
if 'user_claims' not in data:
107-
raise JWTDecodeError("Missing claim: user_claims")
111+
data['user_claims'] = {}
108112
if csrf:
109113
if 'csrf' not in data:
110114
raise JWTDecodeError("Missing claim: csrf")

tests/test_jwt_encode_decode.py

+52-13
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,35 @@ def test_encode_access_token(self):
8383
self.assertLessEqual(exp_seconds, 60 * 5)
8484
self.assertGreater(exp_seconds, 60 * 4)
8585

86+
def test_encode_access_token__no_user_claims(self):
87+
'''
88+
To make JWT shorter, do not add `user_claims` if empty.
89+
'''
90+
secret = 'super-totally-secret-key'
91+
algorithm = 'HS256'
92+
token_expire_delta = timedelta(minutes=5)
93+
identity_claim = 'sub'
94+
95+
# `user_claims` is empty dict
96+
with self.app.test_request_context():
97+
identity = 'user1'
98+
token = encode_access_token(identity, secret, algorithm, token_expire_delta,
99+
fresh=False, user_claims={}, csrf=False,
100+
identity_claim=identity_claim)
101+
102+
data = jwt.decode(token, secret, algorithms=[algorithm])
103+
self.assertNotIn('user_claims', data)
104+
105+
# `user_claims` is None
106+
with self.app.test_request_context():
107+
identity = 'user1'
108+
token = encode_access_token(identity, secret, algorithm, token_expire_delta,
109+
fresh=False, user_claims=None, csrf=False,
110+
identity_claim=identity_claim)
111+
112+
data = jwt.decode(token, secret, algorithms=[algorithm])
113+
self.assertNotIn('user_claims', data)
114+
86115
def test_encode_invalid_access_token(self):
87116
# Check with non-serializable json
88117
with self.app.test_request_context():
@@ -212,6 +241,29 @@ def test_decode_jwt(self):
212241
self.assertEqual(data[identity_claim], 'banana')
213242
self.assertEqual(data['type'], 'refresh')
214243

244+
def test_decode_access_token__no_user_claims(self):
245+
'''
246+
Test decoding a valid access token without `user_claims`.
247+
'''
248+
identity_claim = 'sub'
249+
with self.app.test_request_context():
250+
now = datetime.utcnow()
251+
token_data = {
252+
'exp': now + timedelta(minutes=5),
253+
'iat': now,
254+
'nbf': now,
255+
'jti': 'banana',
256+
identity_claim: 'banana',
257+
'fresh': True,
258+
'type': 'access',
259+
}
260+
encoded_token = jwt.encode(token_data, 'secret', 'HS256').decode('utf-8')
261+
data = decode_jwt(encoded_token, 'secret', 'HS256',
262+
csrf=False, identity_claim=identity_claim)
263+
264+
self.assertIn('user_claims', data)
265+
self.assertEqual(data['user_claims'], {})
266+
215267
def test_decode_invalid_jwt(self):
216268
with self.app.test_request_context():
217269
identity_claim = 'identity'
@@ -284,19 +336,6 @@ def test_decode_invalid_jwt(self):
284336
decode_jwt(encoded_token, 'secret', 'HS256',
285337
csrf=False, identity_claim=identity_claim)
286338

287-
# Missing user claims in access token
288-
with self.assertRaises(JWTDecodeError):
289-
token_data = {
290-
'jti': 'banana',
291-
identity_claim: 'banana',
292-
'exp': datetime.utcnow() + timedelta(minutes=5),
293-
'type': 'access',
294-
'fresh': True
295-
}
296-
encoded_token = jwt.encode(token_data, 'secret', 'HS256').decode('utf-8')
297-
decode_jwt(encoded_token, 'secret', 'HS256',
298-
csrf=False, identity_claim=identity_claim)
299-
300339
# Bad token type
301340
with self.assertRaises(JWTDecodeError):
302341
token_data = {

0 commit comments

Comments
 (0)