import re from datetime import datetime, timedelta, timezone from typing import Any from jose import jwt from passlib.context import CryptContext from app.core.config import settings pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") def normalize_identifier(identifier_type: str, identifier: str) -> str: value = identifier.strip() if identifier_type == "email": return value.lower() if identifier_type == "username": return value if identifier_type == "mobile": return re.sub(r"[\s\-().]", "", value) return value def hash_auth_key(auth_key_material: str) -> str: return pwd_context.hash(auth_key_material) def verify_auth_key(auth_key_material: str, hashed_auth_key: str) -> bool: return pwd_context.verify(auth_key_material, hashed_auth_key) def create_access_token(subject: str, extra_claims: dict[str, Any] | None = None) -> str: expires_at = datetime.now(timezone.utc) + timedelta(minutes=settings.access_token_expire_minutes) payload: dict[str, Any] = {"sub": subject, "exp": expires_at, "iat": datetime.now(timezone.utc)} if extra_claims: payload.update(extra_claims) return jwt.encode(payload, settings.jwt_secret, algorithm=settings.jwt_algorithm)