From 512166e86a5daee9c6b60d36e6752e15871b214d Mon Sep 17 00:00:00 2001 From: Erik Vroon Date: Fri, 9 Feb 2024 16:50:54 +0100 Subject: [PATCH] Replace passlib by bcrypt (#452) fixes https://github.com/evroon/bracket/issues/451 Old password hashes are still valid --- backend/bracket/routes/auth.py | 6 +----- backend/bracket/routes/users.py | 10 ++++------ backend/bracket/utils/db_init.py | 4 ++-- backend/bracket/utils/dummy_records.py | 4 ++-- backend/bracket/utils/security.py | 10 ++++++++-- backend/cli.py | 3 +-- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/backend/bracket/routes/auth.py b/backend/bracket/routes/auth.py index eafcfc16..690d59d9 100644 --- a/backend/bracket/routes/auth.py +++ b/backend/bracket/routes/auth.py @@ -16,7 +16,7 @@ from bracket.schema import tournaments from bracket.sql.tournaments import sql_get_tournament_by_endpoint_name from bracket.sql.users import get_user, get_user_access_to_club, get_user_access_to_tournament from bracket.utils.db import fetch_all_parsed -from bracket.utils.security import pwd_context +from bracket.utils.security import verify_password from bracket.utils.types import assert_some router = APIRouter() @@ -52,10 +52,6 @@ class TokenData(BaseModel): email: str | None = None -def verify_password(plain_password: str, hashed_password: str) -> bool: - return pwd_context.verify(plain_password, hashed_password) - - async def authenticate_user(email: str, password: str) -> UserInDB | None: user = await get_user(email) diff --git a/backend/bracket/routes/users.py b/backend/bracket/routes/users.py index ed7aacc6..392784f1 100644 --- a/backend/bracket/routes/users.py +++ b/backend/bracket/routes/users.py @@ -28,7 +28,7 @@ from bracket.sql.users import ( update_user, update_user_password, ) -from bracket.utils.security import pwd_context, verify_captcha_token +from bracket.utils.security import hash_password, verify_captcha_token from bracket.utils.types import assert_some router = APIRouter() @@ -65,9 +65,7 @@ async def put_user_password( user_public: UserPublic = Depends(user_authenticated), ) -> SuccessResponse: assert user_public.id == user_id - await update_user_password( - assert_some(user_public.id), pwd_context.hash(user_to_update.password) - ) + await update_user_password(assert_some(user_public.id), hash_password(user_to_update.password)) return SuccessResponse() @@ -81,7 +79,7 @@ async def register_user(user_to_register: UserToRegister) -> TokenResponse: user = User( email=user_to_register.email, - password_hash=pwd_context.hash(user_to_register.password), + password_hash=hash_password(user_to_register.password), name=user_to_register.name, created=datetime_utc.now(), account_type=UserAccountType.REGULAR, @@ -114,7 +112,7 @@ async def register_demo_user(user_to_register: DemoUserToRegister) -> TokenRespo username = f"demo-{uuid4()}" user = User( email=f"{username}@example.org", - password_hash=pwd_context.hash(str(uuid4())), + password_hash=hash_password(str(uuid4())), name=username, created=datetime_utc.now(), account_type=UserAccountType.DEMO, diff --git a/backend/bracket/utils/db_init.py b/backend/bracket/utils/db_init.py index c0a9bd37..cd35770c 100644 --- a/backend/bracket/utils/db_init.py +++ b/backend/bracket/utils/db_init.py @@ -67,7 +67,7 @@ from bracket.utils.dummy_records import ( DUMMY_USER, ) from bracket.utils.logging import logger -from bracket.utils.security import pwd_context +from bracket.utils.security import hash_password from bracket.utils.types import BaseModelT, assert_some if TYPE_CHECKING: @@ -82,7 +82,7 @@ async def create_admin_user() -> int: User( name="Admin", email=config.admin_email, - password_hash=pwd_context.hash(config.admin_password), + password_hash=hash_password(config.admin_password), created=datetime_utc.now(), account_type=UserAccountType.REGULAR, ) diff --git a/backend/bracket/utils/dummy_records.py b/backend/bracket/utils/dummy_records.py index 7c2a4b8e..489d9777 100644 --- a/backend/bracket/utils/dummy_records.py +++ b/backend/bracket/utils/dummy_records.py @@ -14,7 +14,7 @@ from bracket.models.db.stage_item import StageItemToInsert, StageType from bracket.models.db.team import Team from bracket.models.db.tournament import Tournament from bracket.models.db.user import User -from bracket.utils.security import pwd_context +from bracket.utils.security import hash_password DUMMY_MOCK_TIME = datetime_utc(2022, 1, 11, 4, 32, 11, tzinfo=ZoneInfo("UTC")) @@ -124,7 +124,7 @@ DUMMY_MATCH1 = Match( DUMMY_USER = User( email="admin@example.com", name="Admin", - password_hash=pwd_context.hash("adminadmin"), + password_hash=hash_password("adminadmin"), created=DUMMY_MOCK_TIME, account_type=UserAccountType.REGULAR, ) diff --git a/backend/bracket/utils/security.py b/backend/bracket/utils/security.py index 89f4450b..b949da95 100644 --- a/backend/bracket/utils/security.py +++ b/backend/bracket/utils/security.py @@ -1,9 +1,15 @@ import aiohttp -from passlib.context import CryptContext +import bcrypt from bracket.config import config -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + +def hash_password(password: str) -> str: + return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") + + +def verify_password(plain_password: str, hashed_password: str) -> bool: + return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8")) async def verify_captcha_token(captcha_token: str) -> bool: diff --git a/backend/cli.py b/backend/cli.py index 7e418cbd..a80edd2b 100755 --- a/backend/cli.py +++ b/backend/cli.py @@ -9,7 +9,6 @@ from bracket.config import config from bracket.database import database from bracket.logger import get_logger from bracket.utils.db_init import sql_create_dev_db -from bracket.utils.security import pwd_context logger = get_logger("cli") @@ -47,7 +46,7 @@ def hash_password() -> None: if config.admin_password is None: logger.error("No admin password is given") else: - hashed_pwd = pwd_context.hash(config.admin_password) + hashed_pwd = hash_password(config.admin_password) logger.info("Hashed password:") logger.info(hashed_pwd)