Skip to content

Commit 6b8588b

Browse files
committed
Validate specific subject of JWT
Allow the user to validate that the subject of a JWT is the specific value that they expect.
1 parent a7fb714 commit 6b8588b

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

jose/jwt.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def encode(claims, key, algorithm=None, headers=None):
5656
return jws.sign(claims, key, headers=headers)
5757

5858

59-
def decode(token, key, algorithms=None, options=None, audience=None, issuer=None):
59+
def decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None):
6060
"""Verifies a JWT string's signature and validates reserved claims.
6161
6262
Args:
@@ -69,6 +69,9 @@ def decode(token, key, algorithms=None, options=None, audience=None, issuer=None
6969
issuer (str): The issuer of the token. If the "iss" claim is
7070
included in the claim set, then the issuer must be included and must equal
7171
the provided claim.
72+
subject (str): The subject of the token. If the "sub" claim is
73+
included in the claim set, then the subject must be included and must equal
74+
the provided claim.
7275
options (dict): A dictionary of options for skipping validation steps.
7376
7477
defaults = {
@@ -127,7 +130,7 @@ def decode(token, key, algorithms=None, options=None, audience=None, issuer=None
127130
if not isinstance(claims, Mapping):
128131
raise JWTError('Invalid payload string: must be a json object')
129132

130-
_validate_claims(claims, audience=audience, issuer=issuer, options=defaults)
133+
_validate_claims(claims, audience=audience, issuer=issuer, subject=subject, options=defaults)
131134

132135
return claims
133136

@@ -333,7 +336,7 @@ def _validate_iss(claims, issuer=None):
333336
raise JWTClaimsError('Invalid issuer')
334337

335338

336-
def _validate_sub(claims):
339+
def _validate_sub(claims, subject=None):
337340
"""Validates that the 'sub' claim is valid.
338341
339342
The "sub" (subject) claim identifies the principal that is the
@@ -346,6 +349,7 @@ def _validate_sub(claims):
346349
347350
Args:
348351
claims (dict): The claims dictionary to validate.
352+
subject (str): The subject of the token.
349353
"""
350354

351355
if 'sub' not in claims:
@@ -354,6 +358,9 @@ def _validate_sub(claims):
354358
if not isinstance(claims['sub'], string_types):
355359
raise JWTClaimsError('Subject must be a string.')
356360

361+
if subject is not None:
362+
if claims.get('sub') != subject:
363+
raise JWTClaimsError('Invalid subject')
357364

358365
def _validate_jti(claims):
359366
"""Validates that the 'jti' claim is valid.
@@ -377,7 +384,7 @@ def _validate_jti(claims):
377384
raise JWTClaimsError('JWT ID must be a string.')
378385

379386

380-
def _validate_claims(claims, audience=None, issuer=None, options=None):
387+
def _validate_claims(claims, audience=None, issuer=None, subject=None, options=None):
381388

382389
leeway = options.get('leeway', 0)
383390

@@ -403,7 +410,7 @@ def _validate_claims(claims, audience=None, issuer=None, options=None):
403410
_validate_iss(claims, issuer=issuer)
404411

405412
if options.get('verify_sub'):
406-
_validate_sub(claims)
413+
_validate_sub(claims, subject=subject)
407414

408415
if options.get('verify_jti'):
409416
_validate_jti(claims)

tests/test_jwt.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,29 @@ def test_sub_invalid(self, key):
380380
with pytest.raises(JWTError):
381381
jwt.decode(token, key)
382382

383+
def test_sub_correct(self, key):
384+
385+
sub = 'subject'
386+
387+
claims = {
388+
'sub': sub
389+
}
390+
391+
token = jwt.encode(claims, key)
392+
jwt.decode(token, key, subject=sub)
393+
394+
def test_sub_incorrect(self, key):
395+
396+
sub = 'subject'
397+
398+
claims = {
399+
'sub': sub
400+
}
401+
402+
token = jwt.encode(claims, key)
403+
with pytest.raises(JWTError):
404+
jwt.decode(token, key, subject='another')
405+
383406
def test_jti_string(self, key):
384407

385408
jti = 'JWT ID'

0 commit comments

Comments
 (0)