From 4cc9c41fe882d572f0d740cb17ff762a5846443d Mon Sep 17 00:00:00 2001 From: Automated Action Date: Wed, 25 Jun 2025 06:41:11 +0000 Subject: [PATCH] Add comprehensive error handling and debugging for signup issues - Enhanced login endpoint with detailed logging for debugging JWT token issues - Added explicit is_google_user and email_verified flags during registration - Added test endpoints for JWT token creation verification - Added debug endpoint to check user authentication status - Improved error handling and logging throughout authentication flow - Better validation for password vs Google OAuth users Debug endpoints added: - POST /auth/test-token - Test JWT token creation - GET /auth/debug/user/{email} - Check user authentication status This will help identify why JWT tokens are not being returned during signin. --- app/routes/auth.py | 120 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 28 deletions(-) diff --git a/app/routes/auth.py b/app/routes/auth.py index bdad83e..c0545b9 100644 --- a/app/routes/auth.py +++ b/app/routes/auth.py @@ -23,6 +23,46 @@ async def test_auth(): } +@router.post("/test-token") +async def test_token_creation(): + """Test endpoint to verify JWT token creation is working""" + try: + test_token = create_access_token(data={"sub": "test@example.com"}) + return { + "message": "Token creation successful", + "token_length": len(test_token), + "token_preview": test_token[:50] + "..." if len(test_token) > 50 else test_token + } + except Exception as e: + logger.error(f"Token creation test failed: {e}") + return { + "message": "Token creation failed", + "error": str(e) + } + + +@router.get("/debug/user/{email}") +async def debug_user_status(email: str, db: Session = Depends(get_db)): + """Debug endpoint to check user status - REMOVE IN PRODUCTION""" + try: + db_user = db.query(User).filter(User.email == email).first() + if not db_user: + return {"message": "User not found", "email": email} + + return { + "email": db_user.email, + "has_password_hash": db_user.password_hash is not None, + "password_hash_length": len(db_user.password_hash) if db_user.password_hash else 0, + "is_google_user": db_user.is_google_user, + "email_verified": db_user.email_verified, + "can_login_with_password": db_user.can_login_with_password(), + "created_at": str(db_user.created_at), + "google_id": db_user.google_id + } + except Exception as e: + return {"error": str(e)} + + class UserCreate(BaseModel): email: EmailStr password: str @@ -63,15 +103,19 @@ async def register(user: UserCreate, db: Session = Depends(get_db)): # Hash password and create user hashed_password = get_password_hash(user.password) + logger.info(f"Password hashed successfully for user: {user.email}") + db_user = User( email=user.email, - password_hash=hashed_password + password_hash=hashed_password, + is_google_user=False, # Explicitly set for password users + email_verified=False # Email not verified for regular registration ) db.add(db_user) db.commit() db.refresh(db_user) - logger.info(f"User registered successfully: {user.email}") + logger.info(f"User registered successfully: {user.email}, can_login_with_password: {db_user.can_login_with_password()}") return UserResponse( id=db_user.id, email=db_user.email, @@ -91,34 +135,54 @@ async def register(user: UserCreate, db: Session = Depends(get_db)): @router.post("/login", response_model=Token) async def login(user: UserLogin, db: Session = Depends(get_db)): - db_user = db.query(User).filter(User.email == user.email).first() - - # Check if user exists - if not db_user: + try: + logger.info(f"Login attempt for email: {user.email}") + + db_user = db.query(User).filter(User.email == user.email).first() + + # Check if user exists + if not db_user: + logger.warning(f"Login failed - user not found: {user.email}") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Incorrect email or password", + headers={"WWW-Authenticate": "Bearer"}, + ) + + logger.info(f"User found: {user.email}, is_google_user: {db_user.is_google_user}, has_password: {db_user.password_hash is not None}") + + # Check if user can login with password + if not db_user.can_login_with_password(): + logger.warning(f"Login failed - Google user attempted password login: {user.email}") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="This account uses Google sign-in. Please use Google to login.", + headers={"WWW-Authenticate": "Bearer"}, + ) + + # Verify password + if not verify_password(user.password, db_user.password_hash): + logger.warning(f"Login failed - incorrect password: {user.email}") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Incorrect email or password", + headers={"WWW-Authenticate": "Bearer"}, + ) + + # Create token + access_token = create_access_token(data={"sub": db_user.email}) + logger.info(f"Login successful for user: {user.email}") + + return {"access_token": access_token, "token_type": "bearer"} + + except HTTPException: + raise + except Exception as e: + logger.error(f"Login error for {user.email}: {str(e)}") raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect email or password", - headers={"WWW-Authenticate": "Bearer"}, + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Internal server error during login" ) - - # Check if user can login with password - if not db_user.can_login_with_password(): - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="This account uses Google sign-in. Please use Google to login.", - headers={"WWW-Authenticate": "Bearer"}, - ) - - # Verify password - if not verify_password(user.password, db_user.password_hash): - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect email or password", - headers={"WWW-Authenticate": "Bearer"}, - ) - - access_token = create_access_token(data={"sub": db_user.email}) - return {"access_token": access_token, "token_type": "bearer"} # Google OAuth Models