xrayvision-backend / app /services /auth_service.py
zohaibcodez's picture
initial deploy
ce4fddb
Raw
History Blame Contribute Delete
2.62 kB
"""JWT authentication and password hashing service."""
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from jose import JWTError, jwt
from passlib.context import CryptContext
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from app.config import get_settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
security = HTTPBearer()
def hash_password(password: str) -> str:
"""Hash a plain-text password using bcrypt."""
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
"""Verify a plain-text password against its hash."""
return pwd_context.verify(plain, hashed)
def create_access_token(user_id: str, email: str) -> str:
"""Create a JWT access token."""
settings = get_settings()
expire = datetime.now(timezone.utc) + timedelta(hours=settings.jwt_expiry_hours)
payload = {
"sub": user_id,
"email": email,
"exp": expire,
"iat": datetime.now(timezone.utc),
}
return jwt.encode(payload, settings.jwt_secret, algorithm=settings.jwt_algorithm)
def decode_token(token: str) -> dict:
"""Decode and validate a JWT token."""
settings = get_settings()
try:
payload = jwt.decode(
token, settings.jwt_secret, algorithms=[settings.jwt_algorithm]
)
return payload
except JWTError as e:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Invalid or expired token: {str(e)}",
headers={"WWW-Authenticate": "Bearer"},
)
def get_current_user_id(
credentials: HTTPAuthorizationCredentials = Depends(security),
) -> str:
"""FastAPI dependency — extract user_id from the Authorization header."""
payload = decode_token(credentials.credentials)
user_id = payload.get("sub")
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token missing user identifier.",
)
return user_id
def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
) -> dict:
"""FastAPI dependency — extract user_id and email from the JWT."""
payload = decode_token(credentials.credentials)
user_id = payload.get("sub")
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token missing user identifier.",
)
return {"id": user_id, "email": payload.get("email", "")}