fix: use bcrypt directly instead of passlib

This commit is contained in:
gilesb
2026-01-07 16:00:22 +00:00
parent 290cb9cadc
commit 95e2bb9a39
2 changed files with 7 additions and 13 deletions

18
auth.py
View File

@@ -11,14 +11,10 @@ from datetime import datetime, timezone, timedelta
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
from passlib.context import CryptContext import bcrypt
from jose import JWTError, jwt from jose import JWTError, jwt
from pydantic import BaseModel from pydantic import BaseModel
# Password hashing (truncate_error=False allows bcrypt to silently truncate)
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto", bcrypt__truncate_error=False)
# JWT settings # JWT settings
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_DAYS = 30 ACCESS_TOKEN_EXPIRE_DAYS = 30
@@ -93,19 +89,17 @@ def save_users(data_dir: Path, users: dict[str, dict]):
json.dump(users, f, indent=2) json.dump(users, f, indent=2)
def truncate_password(password: str) -> str:
"""Truncate password to 72 bytes for bcrypt."""
return password.encode('utf-8')[:72].decode('utf-8', errors='ignore')
def hash_password(password: str) -> str: def hash_password(password: str) -> str:
"""Hash a password (truncate to 72 bytes for bcrypt).""" """Hash a password (truncate to 72 bytes for bcrypt)."""
return pwd_context.hash(truncate_password(password)) # Truncate to 72 bytes (bcrypt limit)
pw_bytes = password.encode('utf-8')[:72]
return bcrypt.hashpw(pw_bytes, bcrypt.gensalt()).decode('utf-8')
def verify_password(plain_password: str, hashed_password: str) -> bool: def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a password against its hash.""" """Verify a password against its hash."""
return pwd_context.verify(truncate_password(plain_password), hashed_password) pw_bytes = plain_password.encode('utf-8')[:72]
return bcrypt.checkpw(pw_bytes, hashed_password.encode('utf-8'))
def create_user(data_dir: Path, username: str, password: str, email: Optional[str] = None) -> User: def create_user(data_dir: Path, username: str, password: str, email: Optional[str] = None) -> User:

View File

@@ -2,7 +2,7 @@ fastapi>=0.109.0
uvicorn>=0.27.0 uvicorn>=0.27.0
requests>=2.31.0 requests>=2.31.0
cryptography>=42.0.0 cryptography>=42.0.0
passlib[bcrypt]>=1.7.4 bcrypt>=4.0.0
python-jose[cryptography]>=3.3.0 python-jose[cryptography]>=3.3.0
markdown>=3.5.0 markdown>=3.5.0
python-multipart>=0.0.6 python-multipart>=0.0.6