Source code for app.lib.jwt_utils

from __future__ import annotations

from datetime import (
    UTC,
    datetime,
    timedelta,
)
from typing import (
    TYPE_CHECKING,
    Any,
)
from uuid import uuid4

from joserfc import jwt

from app.config.base import get_settings

if TYPE_CHECKING:
    from joserfc.jwk import OKPKey
    from joserfc.jwt import Token

settings = get_settings()


[docs] def encode_jwt( payload: dict[str, Any], key_obj: OKPKey = settings.jwt.key_object, algorithm: str = settings.jwt.ALGORITHM, expire_minutes: int = settings.jwt.ACCESS_TOKEN_EXPIRE_MINUTES, expire_timedelta: timedelta | None = None, ) -> str: """Encode a JWT based on the provided payload and expiration settings. This function adds standard claims: `iat` (issued at), `exp` (expiration), and `jti` (JWT ID) to the token payload before encoding. Args: payload (dict): The base data to include in the token (e.g., user ID, email). key_obj (OKPKey): The private key used for signing the token. Defaults to the application's configured private key. algorithm (str): The cryptographic algorithm used for signing (e.g., 'Ed25519'). Defaults to the configured algorithm. expire_minutes (int): The token's lifespan in minutes, used only if `expire_timedelta` is not provided. expire_timedelta (timedelta | None): Explicit timedelta defining the token's total lifespan. Overrides `expire_minutes`. Used primarily for Refresh Tokens. Returns: str: The encoded JWT string. """ to_encode = payload.copy() time_now = datetime.now(tz=UTC) expire = time_now + expire_timedelta if expire_timedelta else time_now + timedelta(minutes=expire_minutes) to_encode.update( iat=time_now, exp=expire, jti=str(uuid4()), ) return jwt.encode( header={"alg": algorithm}, claims=to_encode, key=key_obj, algorithms=[algorithm], )
[docs] def decode_jwt( token: str | bytes, key_obj: OKPKey = settings.jwt.key_object, algorithm: str = settings.jwt.ALGORITHM, ) -> Token: """Decode and validate a JWT using the application's key. This function automatically verifies the token's signature and standard claims (such as expiration time). Args: token (str | bytes): The encoded JWT string or bytes to be decoded. key_obj (OKPKey): The key used for verifying the token's signature. Defaults to the application's configured key. algorithm (str): The cryptographic algorithm used for verification (e.g., 'Ed25519'). Defaults to the configured algorithm. Returns: Token: The extracted token object, which contains header and claims. Raises: joserfc.errors.BadSignatureError: If the token signature verification fails. joserfc.errors.InvalidPayloadError: If the token's payload is not a valid JSON object. """ return jwt.decode( value=token, key=key_obj, algorithms=[algorithm], )