doe/be/app/core/test_security.py
2025-03-30 19:42:32 +02:00

86 lines
3.2 KiB
Python

# Example: be/tests/core/test_security.py
import pytest
from datetime import timedelta
from jose import jwt, JWTError
import time
from app.core.security import (
hash_password,
verify_password,
create_access_token,
verify_access_token,
)
from app.config import settings # Import settings for testing JWT config
# --- Password Hashing Tests ---
def test_hash_password_returns_string():
password = "testpassword"
hashed = hash_password(password)
assert isinstance(hashed, str)
assert password != hashed # Ensure it's not plain text
def test_verify_password_correct():
password = "correct_password"
hashed = hash_password(password)
assert verify_password(password, hashed) is True
def test_verify_password_incorrect():
hashed = hash_password("correct_password")
assert verify_password("wrong_password", hashed) is False
def test_verify_password_invalid_hash_format():
# Passlib's verify handles many format errors gracefully
assert verify_password("any_password", "invalid_hash_string") is False
# --- JWT Tests ---
def test_create_access_token():
subject = "testuser@example.com"
token = create_access_token(subject=subject)
assert isinstance(token, str)
# Decode manually for basic check (verification done in verify_access_token tests)
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
assert payload["sub"] == subject
assert "exp" in payload
assert isinstance(payload["exp"], int)
def test_verify_access_token_valid():
subject = "test_subject_valid"
token = create_access_token(subject=subject)
payload = verify_access_token(token)
assert payload is not None
assert payload["sub"] == subject
def test_verify_access_token_invalid_signature():
subject = "test_subject_invalid_sig"
token = create_access_token(subject=subject)
# Attempt to verify with a wrong key
wrong_key = settings.SECRET_KEY + "wrong"
with pytest.raises(JWTError): # Decoding with wrong key should raise JWTError internally
jwt.decode(token, wrong_key, algorithms=[settings.ALGORITHM])
# Our verify function should catch this and return None
assert verify_access_token(token + "tamper") is None # Tampering token often invalidates sig
# Note: Testing verify_access_token directly returning None for wrong key is tricky
# as the error happens *during* jwt.decode. We rely on it catching JWTError.
def test_verify_access_token_expired():
# Create a token that expires almost immediately
subject = "test_subject_expired"
expires_delta = timedelta(seconds=-1) # Expired 1 second ago
token = create_access_token(subject=subject, expires_delta=expires_delta)
# Wait briefly just in case of timing issues, though negative delta should guarantee expiry
time.sleep(0.1)
# Decoding expired token raises ExpiredSignatureError internally
with pytest.raises(JWTError): # Specifically ExpiredSignatureError, but JWTError catches it
jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
# Our verify function should catch this and return None
assert verify_access_token(token) is None
def test_verify_access_token_malformed():
assert verify_access_token("this.is.not.a.valid.token") is None