Skip to content

Latest commit

 

History

History
666 lines (498 loc) · 16.2 KB

File metadata and controls

666 lines (498 loc) · 16.2 KB

🚀 Authentication System Implementation Guide

MedicSense AI - Healthcare-Grade Authentication

This guide walks you through implementing the confusion-free authentication system.


📋 PRE-IMPLEMENTATION CHECKLIST

Before you begin, ensure you have:

  • Backend code in backend/ directory
  • Frontend code in frontend/ directory
  • Python 3.8+ installed
  • Node.js installed (for Firebase)
  • Google OAuth credentials configured in Firebase

🔧 STEP 1: Install Dependencies

Backend Dependencies

cd backend
pip install bcrypt==4.1.2

Verify installation:

python -c "import bcrypt; print('✅ bcrypt installed:', bcrypt.__version__)"

Expected output:

✅ bcrypt installed: 4.1.2

📁 STEP 2: Verify New Files

Check that these new files were created:

backend/
├── password_utils.py    ← Password hashing utilities
├── auth_routes.py       ← New authentication endpoints
└── requirements.txt     ← Updated with bcrypt

Test password utilities:

cd backend
python password_utils.py

Expected output:

🔐 Password Utilities Test
==================================================

1. Hashing password: SecurePassword123
   Hash: $2b$12$...

2. Verifying correct password...
   ✅ Valid: True

3. Verifying wrong password...
   ❌ Valid: False

4. Testing password strength...
   [strength assessments]

5. Generating secure token...
   Token: [random secure token]

✅ All tests completed!

🔌 STEP 3: Integrate Authentication Routes

Option A: Automatic Integration (Recommended)

Add these lines to backend/app.py after your imports:

# Add this import at the top with other imports
from auth_routes import register_auth_routes

# Add this line after initializing Flask app and before defining routes
# Should be around line 20-30, after:
# app = Flask(__name__)
# CORS(app)

# Register authentication routes
register_auth_routes(app, db, auth_manager, otp_service)

Exact integration location in app.py:

# Line 1-20: Existing imports
from flask import Flask, jsonify, request, send_from_directory
from flask_cors import CORS
# ... other imports ...

app = Flask(__name__)
CORS(app)

# Initialize medical modules
analyzer = SymptomAnalyzer()
classifier = SeverityClassifier()
emergency = EmergencyDetector()

# ADD THIS LINE HERE (after CORS, before route definitions):
from auth_routes import register_auth_routes
register_auth_routes(app, db, auth_manager, otp_service)

# Load knowledge bases
with open("medical_kb.json", "r") as f:
    MEDICAL_KB = json.load(f)
# ... rest of code ...

Option B: Manual Integration (If you prefer more control)

Instead of using register_auth_routes(), you can copy the route definitions from auth_routes.py directly into app.py. This gives you more control but requires more maintenance.


🗄️ STEP 4: Update Database Schema

The database.py file has been updated with new methods. Verify they exist:

cd backend
python -c "from database import db; print('✅ Database methods:', dir(db))"

You should see these new methods:

  • get_user_by_email
  • get_user_by_google_id
  • get_user_by_phone

Backup Existing Data

IMPORTANT: Backup before testing

cd backend/data
cp users.json users.backup.json

🧪 STEP 5: Test Backend Locally

Start the Backend Server

cd backend
python app.py

Expected output:

✅ Authentication routes registered successfully
 * Running on http://127.0.0.1:5000

Test Authentication Endpoints

Open a new PowerShell window and test:

Test 1: Email/Password Signup

curl -X POST http://localhost:5000/api/auth/signup `
  -H "Content-Type: application/json" `
  -d '{"email":"test@example.com","password":"Test123","name":"Test User","phoneCode":"+91","phone":"9999999999"}'

Expected response:

{
  "success": true,
  "message": "Verification code sent to your phone.",
  "action": "verify_otp",
  "phone": "+919999999999",
  "otp": "123456"
}

Test 2: Verify OTP

curl -X POST http://localhost:5000/api/auth/verify-otp `
  -H "Content-Type: application/json" `
  -d '{"phone":"+919999999999","otp":"123456"}'

Expected response:

{
  "success": true,
  "message": "Account created successfully!",
  "user": {
    "id": "...",
    "email": "test@example.com",
    "name": "Test User",
    "authMethod": "email_password"
  },
  "token": "...",
  "isNewUser": true
}

Test 3: Check User in Database

cd backend/data
cat users.json

You should see your test user with:

  • auth_method: "email_password"
  • password_hash: (bcrypt hash starting with $2b$)
  • NO google_id field

🎨 STEP 6: Update Frontend Integration

Update auth.html JavaScript

The frontend UI stays the same, but we need to update the endpoint calls.

Find these sections in frontend/auth.html and update:

Update Signup Function (around line 380)

OLD CODE:

async function handleSignup(e) {
    // ... existing code ...

    try {
        // OLD: Manual OTP sending
        await sendOTP(fullPhone);
    }
}

NEW CODE:

async function handleSignup(e) {
  e.preventDefault();
  hideMessages();

  const name = document.getElementById("signupName").value;
  const email = document.getElementById("signupEmail").value;
  const phoneCode = document.getElementById("signupPhoneCode").value;
  const phone = document.getElementById("signupPhone").value;
  const password = document.getElementById("signupPassword").value;
  const confirmPassword = document.getElementById(
    "signupConfirmPassword"
  ).value;

  if (password !== confirmPassword) {
    showError("Passwords do not match");
    return;
  }

  const btn = document.getElementById("signupBtn");
  btn.disabled = true;
  btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Signing up...';

  try {
    // NEW: Call new signup endpoint
    const response = await fetch("http://localhost:5000/api/auth/signup", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        name,
        email,
        password,
        phoneCode,
        phone,
      }),
    });

    const data = await response.json();

    if (data.success) {
      currentPhone = data.phone;
      showSuccess(data.message);

      // Show OTP section
      document.getElementById("otpSection").classList.add("active");
      document.getElementById("signupForm").classList.remove("active");

      // Auto-fill OTP in development (remove in production)
      if (data.otp) {
        document.getElementById("otpInput").value = data.otp;
      }
    } else {
      showError(data.message);
      btn.disabled = false;
      btn.innerHTML = '<i class="fas fa-user-plus"></i> Sign Up';
    }
  } catch (error) {
    showError("Signup failed: " + error.message);
    btn.disabled = false;
    btn.innerHTML = '<i class="fas fa-user-plus"></i> Sign Up';
  }
}

Update Login Function (around line 350)

NEW CODE:

async function handleLogin(e) {
  e.preventDefault();
  hideMessages();

  const email = document.getElementById("loginEmail").value;
  const phoneCode = document.getElementById("loginPhoneCode").value;
  const phone = document.getElementById("loginPhone").value;
  const password = document.getElementById("loginPassword").value;

  const btn = document.getElementById("loginBtn");
  btn.disabled = true;
  btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Logging in...';

  try {
    // NEW: Call new login endpoint
    const response = await fetch("http://localhost:5000/api/auth/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        email,
        password,
        phoneCode,
        phone,
      }),
    });

    const data = await response.json();

    if (data.success) {
      currentPhone = data.phone;
      showSuccess(data.message);

      // Show OTP section
      document.getElementById("otpSection").classList.add("active");
      document.getElementById("loginForm").classList.remove("active");

      // Auto-fill OTP in development (remove in production)
      if (data.otp) {
        document.getElementById("otpInput").value = data.otp;
      }
    } else {
      // Show helpful error with recovery options
      showError(data.message);

      if (data.recovery && data.recovery.options) {
        const recoveryHTML = `
                    <div style="margin-top: 1rem; padding: 1rem; background: #fff3cd; border-radius: 8px;">
                        <strong>Try these options:</strong>
                        <ul style="margin: 0.5rem 0; padding-left: 1.5rem;">
                            ${data.recovery.options
                              .map((opt) => `<li>${opt}</li>`)
                              .join("")}
                        </ul>
                    </div>
                `;
        document.getElementById("errorMessage").innerHTML += recoveryHTML;
      }

      btn.disabled = false;
      btn.innerHTML = '<i class="fas fa-sign-in-alt"></i> Login';
    }
  } catch (error) {
    showError("Login failed: " + error.message);
    btn.disabled = false;
    btn.innerHTML = '<i class="fas fa-sign-in-alt"></i> Login';
  }
}

Update Google Auth Function (around line 490)

NEW CODE:

async function handleGoogleAuth() {
  try {
    // Wait for Firebase to be ready
    if (!window.firebaseAuth) {
      await new Promise((resolve) => {
        window.addEventListener("firebase-ready", resolve, { once: true });
      });
    }

    const { auth, signInWithPopup, GoogleAuthProvider } = window.firebaseAuth;
    const provider = new GoogleAuthProvider();

    // Sign in with Google
    const result = await signInWithPopup(auth, provider);
    const user = result.user;

    // Get ID token
    const idToken = await user.getIdToken();

    // Send to backend
    const response = await fetch("http://localhost:5000/api/auth/google", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        idToken: idToken,
        user: {
          uid: user.uid,
          email: user.email,
          displayName: user.displayName,
        },
      }),
    });

    const data = await response.json();

    if (data.success) {
      // Save session
      localStorage.setItem("medicsense_token", data.token);
      localStorage.setItem("medicsense_user", JSON.stringify(data.user));

      showSuccess(data.message);
      setTimeout(() => {
        window.location.href = "index.html";
      }, 1000);
    } else {
      // Show helpful error with recovery options
      showError(data.message);

      if (data.recovery && data.recovery.options) {
        const recoveryHTML = `
                    <div style="margin-top: 1rem; padding: 1rem; background: #fff3cd; border-radius: 8px;">
                        <strong>Try these options:</strong>
                        <ul style="margin: 0.5rem 0; padding-left: 1.5rem;">
                            ${data.recovery.options
                              .map((opt) => `<li>${opt}</li>`)
                              .join("")}
                        </ul>
                    </div>
                `;
        document.getElementById("errorMessage").innerHTML += recoveryHTML;
      }
    }
  } catch (error) {
    console.error("Google auth error:", error);
    showError("Google login failed: " + error.message);
  }
}

🧪 STEP 7: End-to-End Testing

Test Scenario 1: New User - Email/Password Signup

  1. Open http://localhost:5000/auth.html in browser
  2. Click "Sign Up" tab
  3. Fill in:
    • Name: Test User
    • Email: test1@example.com
    • Phone: 9999999991
    • Password: Test123
    • Confirm Password: Test123
  4. Click "Sign Up"
  5. Expected: See "Verification code sent to your phone"
  6. Enter OTP (auto-filled in development)
  7. Click "Verify OTP"
  8. Expected: Redirected to index.html with success message

Test Scenario 2: Existing Email/Password User - Login

  1. Open auth.html
  2. Click "Login" tab
  3. Fill in same credentials
  4. Click "Login"
  5. Expected: OTP sent
  6. Verify OTP
  7. Expected: Logged in successfully

Test Scenario 3: Google User - First Time

  1. Click "Continue with Google"
  2. Select Google account
  3. Expected: Account created, logged in

Test Scenario 4: Confusion Test - Google User Tries Email/Password

  1. Sign out
  2. Try to login with email/password using same email as Google account
  3. Expected: See error: "Authentication failed. Please try 'Continue with Google' or contact support."
  4. Expected: See recovery options listed
  5. Click "Continue with Google"
  6. Expected: Login successful

Test Scenario 5: Confusion Test - Email User Tries Google

  1. Create account with email: test2@example.com + password
  2. Sign out
  3. Try Google login with test2@example.com
  4. Expected: See error: "An account with this email already exists. Please sign in with email and password..."
  5. Expected: See recovery options
  6. Use email/password login
  7. Expected: Login successful

🐛 TROUBLESHOOTING

Issue: "Module 'bcrypt' not found"

Solution:

pip install bcrypt==4.1.2

Issue: "No module named 'auth_routes'"

Solution: Check that auth_routes.py is in the backend/ directory and the import is correct:

from auth_routes import register_auth_routes

Issue: Google login fails

Solution:

  1. Check Firebase configuration in firebase.js
  2. Verify OAuth credentials in Firebase Console
  3. Check browser console for errors

Issue: OTP not sending

Solution: The system uses mock OTP in development. The OTP is returned in the API response:

{
  "otp": "123456"
}

In production, integrate with SMS provider (Twilio, MSG91, etc.)

Issue: "Session expired" error

Solution: Sessions are stored in memory and cleared on server restart. This is normal for development. In production, use Redis or database-backed sessions.


📊 VERIFICATION CHECKLIST

After implementation, verify:

  • Backend starts without errors
  • Authentication routes registered successfully
  • Email/password signup works
  • Email/password login works
  • Google sign-in works
  • Users with Google account can't use email/password
  • Users with email/password account can't use Google (unless explicitly linked)
  • Error messages are helpful and privacy-preserving
  • Recovery options are shown when authentication fails
  • OTP verification works
  • Sessions are created and validated
  • Database stores auth_method correctly
  • Passwords are hashed (not plaintext)

🚀 DEPLOYMENT PREPARATION

Before deploying to production:

  1. Remove Development Shortcuts:

    • Remove OTP from API responses
    • Enable real SMS sending via Twilio/MSG91
    • Set up proper environment variables
  2. Security Hardening:

    • Enable HTTPS (required for Google OAuth)
    • Set secure session cookie settings
    • Configure CORS for production domain
    • Add rate limiting to prevent abuse
  3. Database Migration:

    • Move from JSON files to proper database (PostgreSQL/MongoDB)
    • Set up Redis for session storage
    • Create database backups
  4. Monitoring:

    • Set up error logging (Sentry)
    • Track authentication metrics
    • Monitor failed login attempts

📞 SUPPORT

If you encounter issues:

  1. Check the AUTHENTICATION_SOLUTION.md document for detailed explanation
  2. Review error messages in terminal
  3. Check browser console for frontend errors
  4. Verify database content in backend/data/users.json

✅ SUCCESS CRITERIA

Your authentication system is ready when:

  1. ✅ Users can sign up with email/password
  2. ✅ Users can sign in with Google
  3. ✅ System correctly enforces auth method separation
  4. ✅ Error messages are helpful and guide users
  5. ✅ No user confusion about passwords
  6. ✅ All passwords are hashed with bcrypt
  7. ✅ Sessions work correctly
  8. ✅ 2FA (OTP) works for email/password auth

Congratulations! You now have a healthcare-grade authentication system. 🏥✅


Document Version: 1.0 Last Updated: January 16, 2026 Status: Implementation Guide