fooder-api/fooder/test/utils/test_jwt.py

83 lines
2.8 KiB
Python

from datetime import datetime, timedelta, timezone
import pytest
from jose import jwt
from typing import Literal
from fooder.exc import Unauthorized
from fooder.utils.jwt import AccessToken, RefreshToken, Token
PAST = datetime(2000, 1, 1, tzinfo=timezone.utc)
class WrongKeyToken(Token):
token_type: Literal["test-type"] = "test-type"
secret_key = "wrong-secret"
expire_delta = timedelta(minutes=30)
class TestAccessToken:
def test_encode_decode_roundtrip(self):
now = datetime.now(timezone.utc)
token = AccessToken(exp=AccessToken.calculate_exp(now), sub=42)
decoded = AccessToken.decode(token.encode())
assert decoded.sub == token.sub
def test_calculate_exp(self):
now = datetime.now(timezone.utc)
assert AccessToken.calculate_exp(now) > now
def test_decode_wrong_key_raises(self):
now = datetime.now(timezone.utc)
token = WrongKeyToken(exp=WrongKeyToken.calculate_exp(now), sub=1)
with pytest.raises(Unauthorized):
AccessToken.decode(token.encode())
def test_decode_expired_raises(self):
token = AccessToken(exp=PAST, sub=1)
with pytest.raises(Unauthorized):
AccessToken.decode(token.encode())
def test_encoded_fields(self):
now = datetime.now(timezone.utc)
token = AccessToken(exp=AccessToken.calculate_exp(now), sub=42)
payload = jwt.decode(token.encode(), "", options={"verify_signature": False})
assert "secret_key" not in payload
assert "expire_delta" not in payload
class TestRefreshToken:
def test_encode_decode_roundtrip(self):
now = datetime.now(timezone.utc)
token = RefreshToken(exp=RefreshToken.calculate_exp(now), sub=7)
decoded = RefreshToken.decode(token.encode())
assert decoded.sub == token.sub
def test_calculate_exp(self):
now = datetime.now(timezone.utc)
assert RefreshToken.calculate_exp(now) > now
def test_refresh_token_not_decodable_as_access_token(self):
now = datetime.now(timezone.utc)
token = RefreshToken(exp=RefreshToken.calculate_exp(now), sub=1)
with pytest.raises(Unauthorized):
AccessToken.decode(token.encode())
def test_access_token_not_decodable_as_refresh_token(self):
now = datetime.now(timezone.utc)
token = AccessToken(exp=AccessToken.calculate_exp(now), sub=1)
with pytest.raises(Unauthorized):
RefreshToken.decode(token.encode())
def test_encoded_fields(self):
now = datetime.now(timezone.utc)
token = AccessToken(exp=RefreshToken.calculate_exp(now), sub=42)
payload = jwt.decode(token.encode(), "", options={"verify_signature": False})
assert "secret_key" not in payload
assert "expire_delta" not in payload