Add an auth service for minting and decoding JWTs

This commit is contained in:
Campbell Alden 2026-08-02 22:50:05 +09:00
parent 328f430309
commit 387e2fa490
6 changed files with 77 additions and 4 deletions

45
src/services/auth.py Normal file
View file

@ -0,0 +1,45 @@
from src.config.parse import assert_key_of_type, ParseError
from typing import Any
from dataclasses import dataclass, asdict
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
import jwt
from src.services.users import User
from src.config.auth import Auth as AuthConfig
JWT = str
@dataclass
class Claims:
id: int
@classmethod
def from_user(cls, user: User) -> 'Claims':
return Claims(id=user.id)
@classmethod
def from_dict(cls, claims: dict[str, Any]) -> 'Claims':
assert_key_of_type(claims, 'id', int)
return Claims(id=claims['id'])
class AuthService:
def __init__(self, config: AuthConfig):
self._private_key = Ed25519PrivateKey.from_private_bytes(config.ed25519_private_key.expose_secret())
self._public_key = self._private_key.public_key()
def mint_jwt(self, user: User) -> JWT:
claims = Claims.from_user(user)
return jwt.encode(asdict(claims), self._private_key, algorithm='EdDSA')
def validate_token(self, token: JWT) -> Claims | None:
try:
claims = jwt.decode(token, key=self._public_key, algorithms=['EdDSA'])
except jwt.InvalidTokenError:
return None
try:
return Claims.from_dict(claims)
except ParseError:
return None