Fix test user authentication issues

Fixed email validation and token hashing:
- Changed test user emails from @test.local to @example.com (valid domain)
- Replaced passlib bcrypt for JWT token hashing with SHA-256 (no length limit)
- Improved error handling in SimpleLogin component for validation errors
- Deleted old test users and recreated with valid emails

Credentials:
- Admin: admin@example.com / admin
- User: user@example.com / user

Note: bcrypt still used for password hashing (in auth_service.py),
but SHA-256 for JWT token hashing to avoid 72-byte limit.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
SamoilenkoVadym 2026-01-27 20:09:07 +00:00
parent b284cadb86
commit 8149a98bd6
3 changed files with 32 additions and 21 deletions

View file

@ -8,16 +8,13 @@ import logging
from datetime import datetime, timedelta
from typing import Optional, Dict
import jwt
from passlib.context import CryptContext
import hashlib
from app.config import get_settings
logger = logging.getLogger(__name__)
settings = get_settings()
# Password hashing context
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(
data: Dict,
@ -96,15 +93,15 @@ def decode_token(token: str) -> Optional[Dict]:
def hash_token(token: str) -> str:
"""
Hash token for secure storage
Hash token for secure storage using SHA-256
Args:
token: Token string to hash
Returns:
Hashed token
Hashed token (hex digest)
"""
return pwd_context.hash(token)
return hashlib.sha256(token.encode('utf-8')).hexdigest()
def verify_token_hash(token: str, hashed: str) -> bool:
@ -118,7 +115,7 @@ def verify_token_hash(token: str, hashed: str) -> bool:
Returns:
True if token matches hash
"""
return pwd_context.verify(token, hashed)
return hash_token(token) == hashed
def get_token_subject(token: str) -> Optional[str]:

View file

@ -37,7 +37,7 @@ async def create_test_users():
# Admin user
result = await session.execute(
select(User).where(User.email == "admin@test.local")
select(User).where(User.email == "admin@example.com")
)
admin = result.scalar_one_or_none()
@ -45,7 +45,7 @@ async def create_test_users():
admin = User(
id=uuid.uuid4(),
azure_ad_id="test_admin", # Special flag for test users
email="admin@test.local",
email="admin@example.com",
display_name="Test Admin",
given_name="Admin",
surname="User",
@ -58,13 +58,13 @@ async def create_test_users():
}
)
session.add(admin)
print(f"✅ Created admin user: admin@test.local / admin")
print(f"✅ Created admin user: admin@example.com / admin")
else:
print(f" Admin user already exists")
# Regular user
result = await session.execute(
select(User).where(User.email == "user@test.local")
select(User).where(User.email == "user@example.com")
)
user = result.scalar_one_or_none()
@ -72,7 +72,7 @@ async def create_test_users():
user = User(
id=uuid.uuid4(),
azure_ad_id="test_user", # Special flag for test users
email="user@test.local",
email="user@example.com",
display_name="Test User",
given_name="Test",
surname="User",
@ -85,7 +85,7 @@ async def create_test_users():
}
)
session.add(user)
print(f"✅ Created regular user: user@test.local / user")
print(f"✅ Created regular user: user@example.com / user")
else:
print(f" Regular user already exists")
@ -97,8 +97,8 @@ async def create_test_users():
print("Test users created successfully!")
print("="*60)
print("\n📝 Login credentials:")
print(" Admin: admin@test.local / admin")
print(" User: user@test.local / user")
print(" Admin: admin@example.com / admin")
print(" User: user@example.com / user")
print("\n🔗 Use these at: http://localhost:3000")
print("="*60)

View file

@ -34,19 +34,33 @@ const SimpleLogin: React.FC<SimpleLoginProps> = ({ onLoginSuccess }) => {
onLoginSuccess(response.data.access_token, response.data.user);
} catch (err: any) {
console.error('Login failed:', err);
setError(err.response?.data?.detail || 'Login failed. Please check your credentials.');
// Handle validation errors from FastAPI
if (err.response?.data?.detail) {
const detail = err.response.data.detail;
if (Array.isArray(detail)) {
// Pydantic validation errors
setError(detail.map((e: any) => e.msg).join(', '));
} else if (typeof detail === 'string') {
setError(detail);
} else {
setError('Login failed. Please check your credentials.');
}
} else {
setError('Login failed. Please check your credentials.');
}
} finally {
setIsLoading(false);
}
};
const fillAdmin = () => {
setEmail('admin@test.local');
setEmail('admin@example.com');
setPassword('admin');
};
const fillUser = () => {
setEmail('user@test.local');
setEmail('user@example.com');
setPassword('user');
};
@ -116,8 +130,8 @@ const SimpleLogin: React.FC<SimpleLoginProps> = ({ onLoginSuccess }) => {
<div className="login-info">
<p><strong>Test Accounts:</strong></p>
<ul>
<li>Admin: admin@test.local / admin</li>
<li>User: user@test.local / user</li>
<li>Admin: admin@example.com / admin</li>
<li>User: user@example.com / user</li>
</ul>
</div>
</div>