MedicSense AI - Healthcare-Grade Authentication
This guide walks you through implementing the confusion-free authentication system.
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
cd backend
pip install bcrypt==4.1.2Verify installation:
python -c "import bcrypt; print('✅ bcrypt installed:', bcrypt.__version__)"Expected output:
✅ bcrypt installed: 4.1.2
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.pyExpected 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!
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 ...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.
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_emailget_user_by_google_idget_user_by_phone
IMPORTANT: Backup before testing
cd backend/data
cp users.json users.backup.jsoncd backend
python app.pyExpected output:
✅ Authentication routes registered successfully
* Running on http://127.0.0.1:5000
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.jsonYou should see your test user with:
-
auth_method: "email_password" -
password_hash: (bcrypt hash starting with$2b$ ) - NO
google_idfield
The frontend UI stays the same, but we need to update the endpoint calls.
Find these sections in frontend/auth.html and update:
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';
}
}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';
}
}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);
}
}- Open
http://localhost:5000/auth.htmlin browser - Click "Sign Up" tab
- Fill in:
- Name: Test User
- Email: test1@example.com
- Phone: 9999999991
- Password: Test123
- Confirm Password: Test123
- Click "Sign Up"
- Expected: See "Verification code sent to your phone"
- Enter OTP (auto-filled in development)
- Click "Verify OTP"
- Expected: Redirected to index.html with success message
- Open
auth.html - Click "Login" tab
- Fill in same credentials
- Click "Login"
- Expected: OTP sent
- Verify OTP
- Expected: Logged in successfully
- Click "Continue with Google"
- Select Google account
- Expected: Account created, logged in
- Sign out
- Try to login with email/password using same email as Google account
- Expected: See error: "Authentication failed. Please try 'Continue with Google' or contact support."
- Expected: See recovery options listed
- Click "Continue with Google"
- Expected: Login successful
- Create account with email: test2@example.com + password
- Sign out
- Try Google login with test2@example.com
- Expected: See error: "An account with this email already exists. Please sign in with email and password..."
- Expected: See recovery options
- Use email/password login
- Expected: Login successful
Solution:
pip install bcrypt==4.1.2Solution:
Check that auth_routes.py is in the backend/ directory and the import is correct:
from auth_routes import register_auth_routesSolution:
- Check Firebase configuration in
firebase.js - Verify OAuth credentials in Firebase Console
- Check browser console for errors
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.)
Solution: Sessions are stored in memory and cleared on server restart. This is normal for development. In production, use Redis or database-backed sessions.
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)
-
Remove Development Shortcuts:
- Remove OTP from API responses
- Enable real SMS sending via Twilio/MSG91
- Set up proper environment variables
-
Security Hardening:
- Enable HTTPS (required for Google OAuth)
- Set secure session cookie settings
- Configure CORS for production domain
- Add rate limiting to prevent abuse
-
Database Migration:
- Move from JSON files to proper database (PostgreSQL/MongoDB)
- Set up Redis for session storage
- Create database backups
-
Monitoring:
- Set up error logging (Sentry)
- Track authentication metrics
- Monitor failed login attempts
If you encounter issues:
- Check the
AUTHENTICATION_SOLUTION.mddocument for detailed explanation - Review error messages in terminal
- Check browser console for frontend errors
- Verify database content in
backend/data/users.json
Your authentication system is ready when:
- ✅ Users can sign up with email/password
- ✅ Users can sign in with Google
- ✅ System correctly enforces auth method separation
- ✅ Error messages are helpful and guide users
- ✅ No user confusion about passwords
- ✅ All passwords are hashed with bcrypt
- ✅ Sessions work correctly
- ✅ 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