Cleaned up unused imports including `timezone` and `ExpiredSignatureError`. Streamlined the import structure to improve readability and maintainability. These changes do not affect functionality but enhance code clarity.
112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
from datetime import timedelta, datetime
|
|
|
|
import pytest
|
|
from jose import jwt, JWTError
|
|
|
|
from app.auth.security import (
|
|
get_password_hash, verify_password,
|
|
create_access_token, create_refresh_token,
|
|
decode_token, SECRET_KEY, ALGORITHM
|
|
)
|
|
from app.schemas.token import TokenPayload
|
|
|
|
|
|
def test_password_hashing():
|
|
plain_password = "securepassword123"
|
|
hashed_password = get_password_hash(plain_password)
|
|
|
|
# Ensure hashed passwords are not the same
|
|
assert hashed_password != plain_password
|
|
# Test password verification
|
|
assert verify_password(plain_password, hashed_password)
|
|
assert not verify_password("wrongpassword", hashed_password)
|
|
|
|
|
|
def test_access_token_creation():
|
|
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
|
token = create_access_token({"sub": user_id})
|
|
decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
|
|
assert decoded_payload.get("sub") == user_id
|
|
assert decoded_payload.get("type") == "access"
|
|
|
|
|
|
def test_refresh_token_creation():
|
|
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
|
token = create_refresh_token({"sub": user_id})
|
|
decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
|
|
|
assert decoded_payload.get("sub") == user_id
|
|
assert decoded_payload.get("type") == "refresh"
|
|
|
|
|
|
def test_decode_token_valid():
|
|
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
|
access_token = create_access_token({"sub": user_id})
|
|
token_payload = decode_token(access_token)
|
|
|
|
assert isinstance(token_payload, TokenPayload)
|
|
assert token_payload.sub == user_id
|
|
assert token_payload.type == "access"
|
|
|
|
|
|
def test_decode_token_expired():
|
|
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
|
token = create_access_token({"sub": user_id}, expires_delta=timedelta(seconds=-1))
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(token)
|
|
|
|
assert str(exc_info.value) == "Token expired. Please refresh your token to continue."
|
|
|
|
|
|
def test_decode_token_missing_exp():
|
|
# Create a token without the `exp` claim
|
|
payload = {"sub": "123e4567-e89b-12d3-a456-426614174000", "type": "access"}
|
|
token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(token)
|
|
|
|
assert str(exc_info.value) == "Malformed token. Missing required claim."
|
|
|
|
|
|
def test_decode_token_missing_sub():
|
|
# Create a token without the `sub` claim
|
|
payload = {"exp": datetime.now().timestamp() + 60, "type": "access"}
|
|
token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(token)
|
|
|
|
assert str(exc_info.value) == "Malformed token. Missing required claim."
|
|
|
|
|
|
def test_decode_token_invalid_signature():
|
|
# Use a different secret key for signing
|
|
token = jwt.encode({"sub": "123", "type": "access"}, "wrong_secret", algorithm=ALGORITHM)
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(token)
|
|
|
|
assert str(exc_info.value) == "Invalid token."
|
|
|
|
|
|
def test_decode_token_malformed():
|
|
malformed_token = "malformed.header.payload"
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(malformed_token)
|
|
|
|
assert str(exc_info.value) == "Invalid token."
|
|
|
|
|
|
def test_decode_token_invalid_type():
|
|
user_id = "123e4567-e89b-12d3-a456-426614174000"
|
|
token = create_refresh_token({"sub": user_id}) # Token type is "refresh"
|
|
|
|
with pytest.raises(JWTError) as exc_info:
|
|
decode_token(token, required_type="access") # Expecting an access token
|
|
|
|
assert str(exc_info.value) == "Invalid token type: expected 'access', got 'refresh'."
|