Przeglądaj źródła

Fix bcrypt compatibility and session cookie issues

- Replace passlib with direct bcrypt usage to fix compatibility with bcrypt 5.0+
- Add explicit path="/" to session cookies to ensure proper persistence
- Update migration script to use bcrypt directly instead of passlib

Fixes authentication errors and session redirect issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Brad Lance 3 miesięcy temu
rodzic
commit
e4a257e36f
2 zmienionych plików z 18 dodań i 7 usunięć
  1. 12 4
      app/auth.py
  2. 6 3
      app/migrations/add_multi_user.py

+ 12 - 4
app/auth.py

@@ -9,7 +9,7 @@ from typing import Optional
 from fastapi import Depends, HTTPException, status, Request, Response
 from fastapi import Depends, HTTPException, status, Request, Response
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy import select
 from sqlalchemy import select
-from passlib.hash import bcrypt
+import bcrypt
 from cryptography.fernet import Fernet
 from cryptography.fernet import Fernet
 from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
 from itsdangerous import URLSafeTimedSerializer, BadSignature, SignatureExpired
 import base64
 import base64
@@ -27,12 +27,19 @@ SESSION_MAX_AGE = 60 * 60 * 24 * 30  # 30 days
 
 
 def get_password_hash(password: str) -> str:
 def get_password_hash(password: str) -> str:
     """Hash a password using bcrypt."""
     """Hash a password using bcrypt."""
-    return bcrypt.hash(password)
+    # Bcrypt requires bytes
+    password_bytes = password.encode('utf-8')
+    salt = bcrypt.gensalt()
+    hashed = bcrypt.hashpw(password_bytes, salt)
+    # Return as string for storage
+    return hashed.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 bcrypt.verify(plain_password, hashed_password)
+    password_bytes = plain_password.encode('utf-8')
+    hashed_bytes = hashed_password.encode('utf-8')
+    return bcrypt.checkpw(password_bytes, hashed_bytes)
 
 
 
 
 def get_fernet_key() -> bytes:
 def get_fernet_key() -> bytes:
@@ -92,6 +99,7 @@ def set_session_cookie(response: Response, user_id: int):
         key=SESSION_COOKIE_NAME,
         key=SESSION_COOKIE_NAME,
         value=token,
         value=token,
         max_age=SESSION_MAX_AGE,
         max_age=SESSION_MAX_AGE,
+        path="/",
         httponly=True,
         httponly=True,
         samesite="lax",
         samesite="lax",
         # Set secure=True in production with HTTPS
         # Set secure=True in production with HTTPS
@@ -101,7 +109,7 @@ def set_session_cookie(response: Response, user_id: int):
 
 
 def clear_session_cookie(response: Response):
 def clear_session_cookie(response: Response):
     """Clear session cookie."""
     """Clear session cookie."""
-    response.delete_cookie(key=SESSION_COOKIE_NAME)
+    response.delete_cookie(key=SESSION_COOKIE_NAME, path="/")
 
 
 
 
 async def get_current_user(
 async def get_current_user(

+ 6 - 3
app/migrations/add_multi_user.py

@@ -95,10 +95,13 @@ async def run_migration():
             abs_url = "http://localhost:13378"
             abs_url = "http://localhost:13378"
             abs_token = "PLACEHOLDER_TOKEN"
             abs_token = "PLACEHOLDER_TOKEN"
 
 
-        # For now, use a simple hash - will be replaced with proper bcrypt later
+        # Hash the default password using bcrypt
         # Password is "admin123" - user should change this immediately
         # Password is "admin123" - user should change this immediately
-        from passlib.hash import bcrypt
-        default_password = bcrypt.hash("admin123")
+        import bcrypt as bcrypt_lib
+        password_bytes = "admin123".encode('utf-8')
+        salt = bcrypt_lib.gensalt()
+        hashed = bcrypt_lib.hashpw(password_bytes, salt)
+        default_password = hashed.decode('utf-8')
 
 
         await conn.execute(text("""
         await conn.execute(text("""
             INSERT INTO users
             INSERT INTO users