diff --git a/jwt/api_jwt.py b/jwt/api_jwt.py index c9d34a5f6..cbb810ece 100644 --- a/jwt/api_jwt.py +++ b/jwt/api_jwt.py @@ -1,4 +1,5 @@ import json +import warnings from calendar import timegm from collections.abc import Iterable, Mapping from datetime import datetime, timedelta, timezone @@ -75,6 +76,17 @@ def decode_complete( else: options.setdefault("verify_signature", True) + # If the user has set the legacy `verify` argument, and it doesn't match + # what the relevant `options` entry for the argument is, inform the user + # that they're likely making a mistake. + if 'verify' in kwargs and kwargs['verify'] != options['verify_signature']: + warnings.warn( + 'The `verify` argument to `decode` does nothing in PyJWT 2.0 and newer. ' + 'The equivalent is setting `verify_signature` to False in the `options` dictionary. ' + 'This invocation has a mismatch between the kwarg and the option entry.', + category=DeprecationWarning, + ) + if not options["verify_signature"]: options.setdefault("verify_exp", False) options.setdefault("verify_nbf", False) diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py index fa3167a41..4434545ce 100644 --- a/tests/test_api_jwt.py +++ b/tests/test_api_jwt.py @@ -658,3 +658,17 @@ def test_decode_no_algorithms_verify_signature_false(self, jwt, payload): jwt_message = jwt.encode(payload, secret) jwt.decode(jwt_message, secret, options={"verify_signature": False}) + + def test_decode_legacy_verify_warning(self, jwt, payload): + secret = "secret" + jwt_message = jwt.encode(payload, secret) + + with pytest.deprecated_call(): + # The implicit default for options.verify_signature is True, + # but the user sets verify to False. + jwt.decode(jwt_message, secret, verify=False, algorithms=["HS256"]) + + with pytest.deprecated_call(): + # The user explicitly sets verify=True, + # but contradicts it in verify_signature. + jwt.decode(jwt_message, secret, verify=True, options={"verify_signature": False})