File size: 1,952 Bytes
f201243 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
"""
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()
|