Browse Source

🎨 Auto format

pull/15835/head
pre-commit-ci-lite[bot] 1 month ago
committed by GitHub
parent
commit
f2c7d6bbe1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      docs_src/security/tutorial004_an_py310.py
  2. 82
      tests/test_invariant_tutorial004_an_py310.py

4
docs_src/security/tutorial004_an_py310.py

@ -11,7 +11,9 @@ from pydantic import BaseModel
# to get a string like this run: # to get a string like this run:
# openssl rand -hex 32 # openssl rand -hex 32
SECRET_KEY = os.getenv("SECRET_KEY", "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7") SECRET_KEY = os.getenv(
"SECRET_KEY", "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
)
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 ACCESS_TOKEN_EXPIRE_MINUTES = 30

82
tests/test_invariant_tutorial004_an_py310.py

@ -1,47 +1,69 @@
import pytest import base64
import sys import json
import os import os
import sys
from datetime import datetime, timedelta from datetime import datetime, timedelta
import json
import base64 import pytest
# Add the project root to sys.path to import the module # Add the project root to sys.path to import the module
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")))
from docs_src.security.tutorial004_an_py310 import decode_and_validate_token from docs_src.security.tutorial004_an_py310 import decode_and_validate_token
@pytest.mark.parametrize("token_payload", [
# Exact exploit case: token with expired timestamp @pytest.mark.parametrize(
json.dumps({"user_id": "admin", "exp": int((datetime.utcnow() - timedelta(hours=1)).timestamp())}), "token_payload",
[
# Boundary case: token with no expiration claim # Exact exploit case: token with expired timestamp
json.dumps({"user_id": "attacker"}), json.dumps(
{
# Valid input: token with future expiration "user_id": "admin",
json.dumps({"user_id": "user123", "exp": int((datetime.utcnow() + timedelta(hours=1)).timestamp())}), "exp": int((datetime.utcnow() - timedelta(hours=1)).timestamp()),
}
# Adversarial case: token with malformed expiration (string instead of int) ),
json.dumps({"user_id": "evil", "exp": "never"}), # Boundary case: token with no expiration claim
json.dumps({"user_id": "attacker"}),
# Adversarial case: token with far future expiration (beyond reasonable bounds) # Valid input: token with future expiration
json.dumps({"user_id": "admin", "exp": int((datetime.utcnow() + timedelta(days=365*10)).timestamp())}), json.dumps(
]) {
"user_id": "user123",
"exp": int((datetime.utcnow() + timedelta(hours=1)).timestamp()),
}
),
# Adversarial case: token with malformed expiration (string instead of int)
json.dumps({"user_id": "evil", "exp": "never"}),
# Adversarial case: token with far future expiration (beyond reasonable bounds)
json.dumps(
{
"user_id": "admin",
"exp": int((datetime.utcnow() + timedelta(days=365 * 10)).timestamp()),
}
),
],
)
def test_jwt_expiration_validation_invariant(token_payload): def test_jwt_expiration_validation_invariant(token_payload):
"""Invariant: JWT tokens must be rejected if expired or lacking proper expiration validation.""" """Invariant: JWT tokens must be rejected if expired or lacking proper expiration validation."""
# Create a simple JWT-like token (header.payload.signature) # Create a simple JWT-like token (header.payload.signature)
header = base64.urlsafe_b64encode(json.dumps({"alg": "HS256", "typ": "JWT"}).encode()).rstrip(b'=') header = base64.urlsafe_b64encode(
payload = base64.urlsafe_b64encode(token_payload.encode()).rstrip(b'=') json.dumps({"alg": "HS256", "typ": "JWT"}).encode()
signature = base64.urlsafe_b64encode(b"fakesignature").rstrip(b'=') ).rstrip(b"=")
payload = base64.urlsafe_b64encode(token_payload.encode()).rstrip(b"=")
signature = base64.urlsafe_b64encode(b"fakesignature").rstrip(b"=")
token = f"{header.decode()}.{payload.decode()}.{signature.decode()}" token = f"{header.decode()}.{payload.decode()}.{signature.decode()}"
try: try:
result = decode_and_validate_token(token) result = decode_and_validate_token(token)
# If token is accepted, it must have a valid future expiration # If token is accepted, it must have a valid future expiration
payload_dict = json.loads(token_payload) payload_dict = json.loads(token_payload)
assert "exp" in payload_dict, "Token without expiration claim should be rejected" assert "exp" in payload_dict, (
"Token without expiration claim should be rejected"
)
assert isinstance(payload_dict["exp"], int), "Expiration must be integer" assert isinstance(payload_dict["exp"], int), "Expiration must be integer"
assert payload_dict["exp"] > int(datetime.utcnow().timestamp()), "Token expiration must be in future" assert payload_dict["exp"] > int(datetime.utcnow().timestamp()), (
except Exception as e: "Token expiration must be in future"
)
except Exception:
# Any validation failure is acceptable - the invariant holds # Any validation failure is acceptable - the invariant holds
assert True assert True

Loading…
Cancel
Save