""" Authentication Service Handles password hashing, JWT token generation, and verification """ import bcrypt from datetime import datetime, timedelta from jose import JWTError, jwt from typing import Optional import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from config import settings class AuthService: """Service for authentication operations.""" @staticmethod def hash_password(password: str) -> str: """Hash a password using bcrypt.""" salt = bcrypt.gensalt() hashed = bcrypt.hashpw(password.encode('utf-8'), salt) return hashed.decode('utf-8') @staticmethod def verify_password(plain_password: str, hashed_password: str) -> bool: """Verify a password against a hash.""" return bcrypt.checkpw( plain_password.encode('utf-8'), hashed_password.encode('utf-8') ) @staticmethod def create_access_token(username: str) -> str: """Create a JWT access token.""" expire = datetime.utcnow() + timedelta(hours=settings.jwt_expiration_hours) to_encode = { "sub": username, "exp": expire, } encoded_jwt = jwt.encode( to_encode, settings.jwt_secret_key, algorithm=settings.jwt_algorithm ) return encoded_jwt @staticmethod def verify_token(token: str) -> Optional[str]: """Verify a JWT token and return the username.""" try: payload = jwt.decode( token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm] ) username: str = payload.get("sub") if username is None: return None return username except JWTError: return None # Global auth service instance auth_service = AuthService()