From 2707498474003883530688a222e4143cf04ad2a7 Mon Sep 17 00:00:00 2001 From: Vishakha Agarwal Date: Tue, 7 Jul 2020 20:22:07 +0530 Subject: [PATCH] Fix "allow expired" feature for JWT GET /v3/auth/tokens?allow_expired=1 works fine with fernet tokens returning the expired token data, whereas it returns exception TokenNotFound for JWT. This patch fixes the same. Change-Id: I03f6c58dce7d140d62055a97063aeb480498e5e6 Closes-Bug: #1886017 --- keystone/tests/unit/test_v3_auth.py | 17 +++++++++++++++++ keystone/token/providers/jws/core.py | 8 +++++--- .../notes/bug-1886017-bc2ad648d57101a2.yaml | 5 +++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/bug-1886017-bc2ad648d57101a2.yaml diff --git a/keystone/tests/unit/test_v3_auth.py b/keystone/tests/unit/test_v3_auth.py index 585f57766c..e710634d01 100644 --- a/keystone/tests/unit/test_v3_auth.py +++ b/keystone/tests/unit/test_v3_auth.py @@ -2628,6 +2628,23 @@ class TokenAPITests(object): with app.test_client() as c: c.get('/v3/users', headers=headers) + def test_fetch_expired_allow_expired_in_expired_window(self): + self.config_fixture.config(group='token', + expiration=10, + allow_expired_window=20) + time = datetime.datetime.utcnow() + with freezegun.freeze_time(time): + token = self._get_project_scoped_token() + + tick = datetime.timedelta(seconds=15) + with freezegun.freeze_time(time + tick): + # after passing expiry time validation fails + self._validate_token(token, expected_status=http.client.NOT_FOUND) + + # but if we pass allow_expired it validates + r = self._validate_token(token, allow_expired=True) + self.assertValidProjectScopedTokenResponse(r) + class TokenDataTests(object): """Test the data in specific token types.""" diff --git a/keystone/token/providers/jws/core.py b/keystone/token/providers/jws/core.py index 93d5dc1bae..7d14d313ca 100644 --- a/keystone/token/providers/jws/core.py +++ b/keystone/token/providers/jws/core.py @@ -175,13 +175,15 @@ class JWSFormatter(object): ) def _decode_token_from_id(self, token_id): + options = dict() + options['verify_exp'] = False for public_key in self.public_keys: try: return jwt.decode( - token_id, public_key, algorithms=JWSFormatter.algorithm + token_id, public_key, algorithms=JWSFormatter.algorithm, + options=options ) - except (jwt.InvalidSignatureError, jwt.DecodeError, - jwt.ExpiredSignatureError): + except (jwt.InvalidSignatureError, jwt.DecodeError): pass # nosec: We want to exhaustively try all public keys raise exception.TokenNotFound(token_id=token_id) diff --git a/releasenotes/notes/bug-1886017-bc2ad648d57101a2.yaml b/releasenotes/notes/bug-1886017-bc2ad648d57101a2.yaml new file mode 100644 index 0000000000..58f99500ee --- /dev/null +++ b/releasenotes/notes/bug-1886017-bc2ad648d57101a2.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + [`bug 1886017 `_] + JWT validation now supports `allow_expired` query parameters.