Spaces:
Sleeping
Sleeping
File size: 3,702 Bytes
0304d75 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | """
tests/test_security_auth.py
============================
Unit tests for security/auth.py — JWT, bcrypt hashing, Fernet encryption.
"""
import time
import pytest
from jose import jwt, JWTError
from security.auth import (
JWT_ALGORITHM,
JWT_SECRET_KEY,
create_jwt_token,
decode_jwt_token,
decrypt_data,
encrypt_data,
hash_password,
verify_password,
)
# ---------------------------------------------------------------------------
# Password hashing (bcrypt)
# ---------------------------------------------------------------------------
class TestPasswordHashing:
def test_hash_is_not_plaintext(self):
hashed = hash_password("mysecret123")
assert hashed != "mysecret123"
assert hashed.startswith("$2b$")
def test_verify_correct_password(self):
hashed = hash_password("testpass")
assert verify_password("testpass", hashed) is True
def test_reject_wrong_password(self):
hashed = hash_password("correct")
assert verify_password("wrong", hashed) is False
def test_different_hashes_for_same_password(self):
"""bcrypt uses a random salt, so two hashes of the same password differ."""
h1 = hash_password("same")
h2 = hash_password("same")
assert h1 != h2
# But both verify
assert verify_password("same", h1)
assert verify_password("same", h2)
# ---------------------------------------------------------------------------
# JWT tokens
# ---------------------------------------------------------------------------
class TestJWT:
def test_create_and_decode(self):
token = create_jwt_token({"sub": "alice"})
payload = decode_jwt_token(token)
assert payload["sub"] == "alice"
assert "exp" in payload
def test_token_contains_custom_data(self):
token = create_jwt_token({"sub": "bob", "role": "admin"})
payload = decode_jwt_token(token)
assert payload["role"] == "admin"
def test_expired_token_raises(self):
from datetime import timedelta
token = create_jwt_token(
{"sub": "charlie"}, expires_delta=timedelta(seconds=-1)
)
with pytest.raises(Exception):
decode_jwt_token(token)
def test_tampered_token_raises(self):
token = create_jwt_token({"sub": "dave"})
# Tamper with the token
tampered = token[:-5] + "XXXXX"
with pytest.raises(Exception):
decode_jwt_token(tampered)
# ---------------------------------------------------------------------------
# Fernet encryption (AES-256)
# ---------------------------------------------------------------------------
class TestFernetEncryption:
def test_encrypt_decrypt_dict(self):
data = {"scores": [0.5, 0.8], "timestamps": [1000.0, 2000.0]}
encrypted = encrypt_data(data)
assert isinstance(encrypted, str)
assert encrypted != str(data)
decrypted = decrypt_data(encrypted)
assert decrypted == data
def test_encrypt_decrypt_list(self):
data = [[1000.0, 0.5], [2000.0, 0.8]]
encrypted = encrypt_data(data)
decrypted = decrypt_data(encrypted)
assert decrypted == data
def test_encrypted_is_not_plaintext(self):
data = {"secret": "value"}
encrypted = encrypt_data(data)
assert "secret" not in encrypted
assert "value" not in encrypted
def test_decrypt_corrupted_returns_none(self):
result = decrypt_data("not-a-valid-ciphertext")
assert result is None
def test_encrypt_empty_list(self):
encrypted = encrypt_data([])
assert decrypt_data(encrypted) == []
|