83 lines
2.8 KiB
Python
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
|