From e5aa933cf92fb941cf14bb3611e7f81fb1c5500c Mon Sep 17 00:00:00 2001 From: "Andrew K. Choi" Date: Fri, 26 Sep 2025 07:07:48 +0900 Subject: [PATCH] bcrypt fix --- -H | 0 -d | 1 + deploy_bcrypt_fix.sh | 43 +++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + shared/auth.py | 35 ++++++++++++++++++++++++----------- 5 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 -H create mode 100644 -d create mode 100755 deploy_bcrypt_fix.sh diff --git a/-H b/-H new file mode 100644 index 0000000..e69de29 diff --git a/-d b/-d new file mode 100644 index 0000000..155fc26 --- /dev/null +++ b/-d @@ -0,0 +1 @@ +{"detail":[{"type":"missing","loc":["body"],"msg":"Field required","input":null,"url":"https://errors.pydantic.dev/2.4/v/missing"}]} \ No newline at end of file diff --git a/deploy_bcrypt_fix.sh b/deploy_bcrypt_fix.sh new file mode 100755 index 0000000..45caac4 --- /dev/null +++ b/deploy_bcrypt_fix.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +# Deploy bcrypt compatibility fix to production server +# Server: 192.168.0.103 + +echo "Deploying bcrypt compatibility fix to production server..." + +# Copy updated files to server +echo "Copying requirements.txt..." +scp requirements.txt trevor@192.168.0.103:/home/trevor/dev/chat/ + +echo "Copying shared/auth.py..." +scp shared/auth.py trevor@192.168.0.103:/home/trevor/dev/chat/shared/ + +echo "Copying user service schemas..." +scp services/user_service/schemas.py trevor@192.168.0.103:/home/trevor/dev/chat/services/user_service/ + +echo "Connecting to server to update dependencies..." +ssh trevor@192.168.0.103 << 'EOF' +cd /home/trevor/dev/chat + +# Stop services +echo "Stopping services..." +./stop_services.sh + +# Update Python packages +echo "Updating bcrypt to version 4.0.1..." +pip install --upgrade bcrypt==4.0.1 +pip install --upgrade passlib[bcrypt]==1.7.4 + +# Verify bcrypt installation +echo "Verifying bcrypt installation..." +python3 -c "import bcrypt; print(f'bcrypt version: {bcrypt.__version__}')" + +# Restart services +echo "Restarting services..." +./start_services_no_docker.sh + +echo "Deployment complete. Services are starting..." +EOF + +echo "Deployment script completed." +echo "Check server logs at 192.168.0.103 to verify bcrypt compatibility fix." \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index ed04a33..d1fa830 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,7 @@ pydantic-settings==2.0.3 python-jose[cryptography]==3.3.0 PyJWT==2.8.0 passlib[bcrypt]==1.7.4 +bcrypt==4.0.1 python-multipart==0.0.6 httpx==0.25.1 aiofiles==23.2.1 diff --git a/shared/auth.py b/shared/auth.py index 98c3a7b..e7a2238 100644 --- a/shared/auth.py +++ b/shared/auth.py @@ -3,6 +3,7 @@ Authentication utilities for all services. This module provides common authentication functionality to avoid circular imports. """ +import logging from datetime import datetime, timedelta from typing import Optional @@ -14,6 +15,9 @@ from passlib.context import CryptContext from shared.config import settings +# Suppress bcrypt version warnings +logging.getLogger("passlib").setLevel(logging.ERROR) + # Password hashing pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -22,21 +26,30 @@ security = HTTPBearer() def verify_password(plain_password: str, hashed_password: str) -> bool: - """Verify password against hash. Apply same truncation as used during hashing.""" - # Apply same truncation logic as during hashing - password_bytes = plain_password.encode('utf-8') - if len(password_bytes) > 72: - plain_password = password_bytes[:72].decode('utf-8', errors='ignore') - return pwd_context.verify(plain_password, hashed_password) + """Verify a password against its hash. Handle bcrypt compatibility issues.""" + try: + # Truncate password to 72 bytes for consistency + password_bytes = plain_password.encode('utf-8') + if len(password_bytes) > 72: + plain_password = password_bytes[:72].decode('utf-8', errors='ignore') + return pwd_context.verify(plain_password, hashed_password) + except Exception as e: + logging.error(f"Error verifying password: {e}") + return False def get_password_hash(password: str) -> str: """Get password hash. Truncate password to 72 bytes if necessary for bcrypt compatibility.""" - # bcrypt has a 72-byte limit, so truncate if necessary - password_bytes = password.encode('utf-8') - if len(password_bytes) > 72: - password = password_bytes[:72].decode('utf-8', errors='ignore') - return pwd_context.hash(password) + try: + # bcrypt has a 72-byte limit, so truncate if necessary + password_bytes = password.encode('utf-8') + if len(password_bytes) > 72: + password = password_bytes[:72].decode('utf-8', errors='ignore') + return pwd_context.hash(password) + except Exception as e: + # Handle bcrypt compatibility issues + logging.error(f"Error hashing password: {e}") + raise ValueError("Password hashing failed. Please use a shorter password.") def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str: