|
1 | 1 | import jwt |
2 | 2 | import pytest |
3 | | -from datetime import datetime, timedelta |
| 3 | +from datetime import timedelta |
| 4 | +import datetime |
4 | 5 | import warnings |
5 | 6 |
|
6 | 7 | from flask import Flask |
7 | | -from jwt import ExpiredSignatureError, InvalidSignatureError, InvalidAudienceError |
| 8 | + |
| 9 | +from jwt import ( |
| 10 | + ExpiredSignatureError, InvalidSignatureError, InvalidAudienceError, |
| 11 | + ImmatureSignatureError |
| 12 | +) |
8 | 13 |
|
9 | 14 | from flask_jwt_extended import ( |
10 | 15 | JWTManager, create_access_token, decode_token, create_refresh_token, |
@@ -37,6 +42,20 @@ def default_access_token(app): |
37 | 42 | } |
38 | 43 |
|
39 | 44 |
|
| 45 | +DATE_IN_FUTURE = datetime.datetime.utcnow() + datetime.timedelta(seconds=5) |
| 46 | + |
| 47 | + |
| 48 | +@pytest.fixture(scope='function') |
| 49 | +def patch_datetime_now(monkeypatch): |
| 50 | + |
| 51 | + class mydatetime(datetime.datetime): |
| 52 | + @classmethod |
| 53 | + def utcnow(cls): |
| 54 | + return DATE_IN_FUTURE |
| 55 | + |
| 56 | + monkeypatch.setattr(datetime, "datetime", mydatetime) |
| 57 | + |
| 58 | + |
40 | 59 | @pytest.mark.parametrize("user_loader_return", [{}, None]) |
41 | 60 | def test_no_user_claims(app, user_loader_return): |
42 | 61 | jwtM = get_jwt_manager(app) |
@@ -107,6 +126,24 @@ def test_never_expire_token(app): |
107 | 126 | assert 'exp' not in decoded |
108 | 127 |
|
109 | 128 |
|
| 129 | +def test_nbf_token_in_future(app, patch_datetime_now): |
| 130 | + """A token that has `nbf` in the future should not be valid and should |
| 131 | + raise a ImmatureSignatureError exception unless the |
| 132 | + `JWT_DECODE_LEEWAY` is (correctly) defined. |
| 133 | +
|
| 134 | + """ |
| 135 | + |
| 136 | + with pytest.raises(ImmatureSignatureError): |
| 137 | + with app.test_request_context(): |
| 138 | + access_token = create_access_token('username') |
| 139 | + decode_token(access_token) |
| 140 | + |
| 141 | + with app.test_request_context(): |
| 142 | + app.config['JWT_DECODE_LEEWAY'] = 10 |
| 143 | + access_token = create_access_token('username') |
| 144 | + decode_token(access_token) |
| 145 | + |
| 146 | + |
110 | 147 | def test_alternate_identity_claim(app, default_access_token): |
111 | 148 | app.config['JWT_IDENTITY_CLAIM'] = 'sub' |
112 | 149 |
|
|
0 commit comments