summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPau Ruiz Safont <psafont@users.noreply.github.com>2020-05-14 15:50:39 +0100
committerGitHub <noreply@github.com>2020-05-14 20:50:39 +0600
commit008490a85932415ec14ab7d61c64216ddaef75fc (patch)
tree85e3da382b296678460c6e7bfdd871f43e677abc
parentc2c91a7bb504f9ff10387972b8ce9353493ed773 (diff)
downloadpyjwt-008490a85932415ec14ab7d61c64216ddaef75fc.tar.gz
Require tweak (#280)
* Use require options as a list, instead of booleans Deprecate the use of the boolean options * Add test for the new require option * Add documentation on how to use the require option Co-authored-by: Pau Ruiz i Safont <psafont@ebi.ac.uk>
-rw-r--r--docs/usage.rst10
-rw-r--r--jwt/api_jwt.py34
-rw-r--r--tests/test_api_jwt.py15
3 files changed, 47 insertions, 12 deletions
diff --git a/docs/usage.rst b/docs/usage.rst
index d2da71a..d012a95 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -242,3 +242,13 @@ Issued At Claim (iat)
jwt.encode({'iat': 1371720939}, 'secret')
jwt.encode({'iat': datetime.utcnow()}, 'secret')
+
+Requiring Presence of Claims
+----------------------------
+
+If you wish to require one or more claims to be present in the claimset, you can set the ``require`` paramenter to include these claims.
+
+.. code-block:: python
+
+ >>jwt.decode(encoded, options={'require': ['exp', 'iss', 'sub']})
+ {u'exp': 1371720939, u'iss': u'urn:foo', u'sub': u'25c37522-f148-4cbf-8ee6-c4a9718dd0af'}
diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py
index 22bfc6a..125b57a 100644
--- a/jwt/api_jwt.py
+++ b/jwt/api_jwt.py
@@ -26,10 +26,11 @@ except ImportError:
class PyJWT(PyJWS):
header_type = "JWT"
+ deprecated_requires = ["require_exp", "require_iat", "require_nbf"]
@staticmethod
def _get_default_options():
- # type: () -> Dict[str, bool]
+ # type: () -> Dict[str, Union[bool, List[str]]]
return {
"verify_signature": True,
"verify_exp": True,
@@ -37,9 +38,7 @@ class PyJWT(PyJWS):
"verify_iat": True,
"verify_aud": True,
"verify_iss": True,
- "require_exp": False,
- "require_iat": False,
- "require_nbf": False,
+ "require": [],
}
def encode(
@@ -128,6 +127,22 @@ class PyJWT(PyJWS):
DeprecationWarning,
)
+ verify_claims = {
+ required
+ for required in self.deprecated_requires
+ if required in options
+ }
+ require_options = options.setdefault("require", [])
+ for opt in verify_claims:
+ opt_claim = opt.split("require_", 1)[1]
+ if options[opt]:
+ require_options.append(opt_claim)
+ warnings.warn(
+ "The {0} parameter is deprecated. Please add {1} to"
+ " the require list in options instead".format(opt, opt_claim),
+ DeprecationWarning,
+ )
+
if isinstance(leeway, timedelta):
leeway = leeway.total_seconds()
@@ -154,14 +169,9 @@ class PyJWT(PyJWS):
self._validate_aud(payload, audience)
def _validate_required_claims(self, payload, options):
- if options.get("require_exp") and payload.get("exp") is None:
- raise MissingRequiredClaimError("exp")
-
- if options.get("require_iat") and payload.get("iat") is None:
- raise MissingRequiredClaimError("iat")
-
- if options.get("require_nbf") and payload.get("nbf") is None:
- raise MissingRequiredClaimError("nbf")
+ for claim in options.get("require", []):
+ if payload.get(claim) is None:
+ raise MissingRequiredClaimError(claim)
def _validate_iat(self, payload, now, leeway):
try:
diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py
index e4065c6..c1759e3 100644
--- a/tests/test_api_jwt.py
+++ b/tests/test_api_jwt.py
@@ -437,6 +437,21 @@ class TestJWT:
assert exc.value.claim == "nbf"
+ def test_decode_should_raise_error_if_claim_required_but_not_present(
+ self, jwt
+ ):
+ claim = "sub"
+ payload = {
+ "some": "payload",
+ # claim not present
+ }
+ token = jwt.encode(payload, "secret")
+
+ with pytest.raises(MissingRequiredClaimError) as exc:
+ jwt.decode(token, "secret", options={"require": [claim]})
+
+ assert exc.value.claim == claim
+
def test_skip_check_signature(self, jwt):
token = (
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"