From dff8d014ec3e7955933e2c0cece6700796602917 Mon Sep 17 00:00:00 2001 From: Hao-Chen2337 <2113996104@qq.com> Date: Thu, 8 Oct 2026 19:52:23 +0800 Subject: [PATCH] api: hash passwords with bcrypt directly, drop passlib passlib 1.7.4 reads bcrypt internals removed in bcrypt 5.0.0, so get_password_hash() raises ValueError. Use bcrypt.hashpw() directly and pin bcrypt; passlib is unused everywhere else. --- api/auth.py | 8 ++++---- docker/api/requirements.txt | 2 +- pyproject.toml | 2 +- tests/unit_tests/test_token_handler.py | 6 ++++++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/auth.py b/api/auth.py index 31f75e1d..4b129a18 100644 --- a/api/auth.py +++ b/api/auth.py @@ -17,7 +17,7 @@ ) from fastapi_users.jwt import SecretType, decode_jwt from fastapi_users.manager import BaseUserManager -from passlib.context import CryptContext +import bcrypt from .config import AuthSettings @@ -96,8 +96,6 @@ async def _decode_and_lookup( class Authentication: """Authentication utility class""" - CRYPT_CTX = CryptContext(schemes=["bcrypt"], deprecated="auto") - def __init__(self, token_url: str): self._settings = AuthSettings() self._token_url = token_url @@ -105,7 +103,9 @@ def __init__(self, token_url: str): @classmethod def get_password_hash(cls, password): """Get a password hash for a given clear text password string""" - return cls.CRYPT_CTX.hash(password) + return bcrypt.hashpw( + password.encode("utf-8"), bcrypt.gensalt() + ).decode("utf-8") def get_jwt_strategy(self) -> DualSecretJWTStrategy: """Get JWT strategy for authentication backend""" diff --git a/docker/api/requirements.txt b/docker/api/requirements.txt index 48ddf6b6..c93bd7a4 100644 --- a/docker/api/requirements.txt +++ b/docker/api/requirements.txt @@ -5,7 +5,7 @@ fastapi-users[beanie, oauth]==15.0.5 fastapi-users-db-beanie==5.0.0 MarkupSafe==2.0.1 pymongo==4.16.0 -passlib==1.7.4 +bcrypt==5.0.0 pydantic==2.9.2 pymongo-migrate==0.11.0 python-jose[cryptography]==3.5.0 diff --git a/pyproject.toml b/pyproject.toml index f4caf409..5c6ee588 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ dependencies = [ "fastapi-users-db-beanie == 5.0.0", "MarkupSafe == 3.0.3", "pymongo == 4.17.0", - "passlib == 1.7.4", + "bcrypt == 5.0.0", "pydantic == 2.13.4", "pymongo-migrate == 1.0.0", "python-jose[cryptography] == 3.5.0", diff --git a/tests/unit_tests/test_token_handler.py b/tests/unit_tests/test_token_handler.py index 0b57c863..a7743a7c 100644 --- a/tests/unit_tests/test_token_handler.py +++ b/tests/unit_tests/test_token_handler.py @@ -10,6 +10,7 @@ import pytest +from api.auth import Authentication from api.models import User @@ -74,3 +75,8 @@ async def test_token_endpoint_incorrect_password( print("response json", response.json()) assert response.status_code == 400 assert response.json() == {"detail": "LOGIN_BAD_CREDENTIALS"} + + +def test_get_password_hash(): + hashed = Authentication.get_password_hash("test-password") + assert hashed.startswith("$2b$12$")