diff --git a/backend/app/core/security.py b/backend/app/core/security.py index 7aff7cfb32..9f61684e07 100644 --- a/backend/app/core/security.py +++ b/backend/app/core/security.py @@ -1,14 +1,11 @@ from datetime import datetime, timedelta, timezone from typing import Any +import bcrypt import jwt -from passlib.context import CryptContext from app.core.config import settings -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") - - ALGORITHM = "HS256" @@ -20,8 +17,11 @@ def create_access_token(subject: str | Any, expires_delta: timedelta) -> str: def verify_password(plain_password: str, hashed_password: str) -> bool: - return pwd_context.verify(plain_password, hashed_password) + return bcrypt.checkpw( + plain_password.encode("utf-8"), + hashed_password.encode("utf-8"), + ) def get_password_hash(password: str) -> str: - return pwd_context.hash(password) + return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") diff --git a/backend/pyproject.toml b/backend/pyproject.toml index d1fbd0641c..c431949c83 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -7,7 +7,6 @@ dependencies = [ "fastapi[standard]<1.0.0,>=0.114.2", "python-multipart<1.0.0,>=0.0.7", "email-validator<3.0.0.0,>=2.1.0.post1", - "passlib[bcrypt]<2.0.0,>=1.7.4", "tenacity<9.0.0,>=8.2.3", "pydantic>2.0", "emails<1.0,>=0.6", @@ -16,8 +15,7 @@ dependencies = [ "httpx<1.0.0,>=0.25.1", "psycopg[binary]<4.0.0,>=3.1.13", "sqlmodel<1.0.0,>=0.0.21", - # Pin bcrypt until passlib supports the latest - "bcrypt==4.3.0", + "bcrypt>=4.3.0", "pydantic-settings<3.0.0,>=2.2.1", "sentry-sdk[fastapi]<2.0.0,>=1.40.6", "pyjwt<3.0.0,>=2.8.0", diff --git a/backend/uv.lock b/backend/uv.lock index fdaaf98efe..fa6ce44872 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -56,7 +56,6 @@ dependencies = [ { name = "fastapi", extra = ["standard"] }, { name = "httpx" }, { name = "jinja2" }, - { name = "passlib", extra = ["bcrypt"] }, { name = "psycopg", extra = ["binary"] }, { name = "pydantic" }, { name = "pydantic-settings" }, @@ -80,13 +79,12 @@ dev = [ [package.metadata] requires-dist = [ { name = "alembic", specifier = ">=1.12.1,<2.0.0" }, - { name = "bcrypt", specifier = "==4.3.0" }, + { name = "bcrypt", specifier = ">=4.3.0" }, { name = "email-validator", specifier = ">=2.1.0.post1,<3.0.0.0" }, { name = "emails", specifier = ">=0.6,<1.0" }, { name = "fastapi", extras = ["standard"], specifier = ">=0.114.2,<1.0.0" }, { name = "httpx", specifier = ">=0.25.1,<1.0.0" }, { name = "jinja2", specifier = ">=3.1.4,<4.0.0" }, - { name = "passlib", extras = ["bcrypt"], specifier = ">=1.7.4,<2.0.0" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.1.13,<4.0.0" }, { name = "pydantic", specifier = ">2.0" }, { name = "pydantic-settings", specifier = ">=2.2.1,<3.0.0" }, @@ -838,20 +836,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 }, ] -[[package]] -name = "passlib" -version = "1.7.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/06/9da9ee59a67fae7761aab3ccc84fa4f3f33f125b370f1ccdb915bf967c11/passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04", size = 689844 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", size = 525554 }, -] - -[package.optional-dependencies] -bcrypt = [ - { name = "bcrypt" }, -] - [[package]] name = "platformdirs" version = "4.3.6"