Skip to content

Commit

Permalink
Check provided claims for type correctness
Browse files Browse the repository at this point in the history
Issue #239 brought up that check_claims are not actually checked to be
of the right type and this can lead to confusion in some case, as well
as defer error reporting after potentially costly signature
computations.

Check for general claims type validity upfront where appropriate.

Resolves #239

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Sep 17, 2021
1 parent 7adb86f commit 14c942d
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
18 changes: 15 additions & 3 deletions jwcrypto/jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ def __init__(self, header=None, claims=None, jwt=None, key=None,
self._reg_claims = default_claims

if check_claims is not None:
if check_claims is not False:
self._check_check_claims(check_claims)
self._check_claims = check_claims

if claims is not None:
Expand Down Expand Up @@ -302,13 +304,13 @@ def _add_default_claims(self, claims):
self._add_jti_claim(claims)

def _check_string_claim(self, name, claims):
if name not in claims:
if name not in claims or claims[name] is None:
return
if not isinstance(claims[name], str):
raise JWTInvalidClaimFormat("Claim %s is not a StringOrURI type")

def _check_array_or_string_claim(self, name, claims):
if name not in claims:
if name not in claims or claims[name] is None:
return
if isinstance(claims[name], list):
if any(not isinstance(claim, str) for claim in claims):
Expand All @@ -319,7 +321,7 @@ def _check_array_or_string_claim(self, name, claims):
"Claim %s is not a StringOrURI type" % (name, ))

def _check_integer_claim(self, name, claims):
if name not in claims:
if name not in claims or claims[name] is None:
return
try:
int(claims[name])
Expand Down Expand Up @@ -353,6 +355,16 @@ def _check_default_claims(self, claims):
if 'nbf' in claims:
self._check_nbf(claims['nbf'], time.time(), self._leeway)

def _check_check_claims(self, check_claims):
self._check_string_claim('iss', check_claims)
self._check_string_claim('sub', check_claims)
self._check_string_claim('aud', check_claims)
self._check_integer_claim('exp', check_claims)
self._check_integer_claim('nbf', check_claims)
self._check_integer_claim('iat', check_claims)
self._check_string_claim('jti', check_claims)
self._check_string_claim('typ', check_claims)

def _check_provided_claims(self):
# check_claims can be set to False to skip any check
if self._check_claims is False:
Expand Down
9 changes: 9 additions & 0 deletions jwcrypto/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,15 @@ def test_Issue_209(self):
# the oct key before hitting the ES one
jwt.JWT(jwt=token, key=ks)

def test_Issue_239(self):
claims = {"aud": "www.example.com"}
check_claims = {"aud": ["www.example.com", "account"]}
key = jwk.JWK(generate='oct', size=256)
token = jwt.JWT(header={"alg": "HS256"}, claims=claims)
token.make_signed_token(key)
self.assertRaises(jwt.JWTInvalidClaimFormat, jwt.JWT, key=key,
jwt=token.serialize(), check_claims=check_claims)


class ConformanceTests(unittest.TestCase):

Expand Down

0 comments on commit 14c942d

Please sign in to comment.