from datetime import datetime, timedelta from typing import Any, Optional import os from jose import jwt from pydantic import ValidationError from app.schemas.token import TokenPayload # Get JWT settings from environment variables SECRET_KEY = os.getenv("SECRET_KEY", "supersecretkey") ALGORITHM = os.getenv("ALGORITHM", "HS256") ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", 30)) REFRESH_TOKEN_EXPIRE_DAYS = int(os.getenv("REFRESH_TOKEN_EXPIRE_DAYS", 7)) def create_access_token(subject: str | Any, expires_delta: Optional[timedelta] = None) -> str: """ Create a new JWT access token """ if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) to_encode = {"exp": expire, "sub": str(subject)} encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt def create_refresh_token(subject: str | Any, expires_delta: Optional[timedelta] = None) -> str: """ Create a new JWT refresh token """ if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS) to_encode = {"exp": expire, "sub": str(subject)} encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt def verify_token(token: str) -> Optional[TokenPayload]: """ Verify and decode a JWT token """ try: payload = jwt.decode( token, SECRET_KEY, algorithms=[ALGORITHM] ) token_data = TokenPayload(**payload) if datetime.fromtimestamp(token_data.exp) < datetime.utcnow(): return None return token_data except (jwt.JWTError, ValidationError): return None