A simple Flask web application demonstrating multi-factor authentication (MFA) using email OTP, WhatsApp OTP (via UltraMSG), and TOTP (Google Authenticator). This repo is intended as a demo or starting point for adding MFA to a web application.
- User signup with email and WhatsApp OTP verification
- TOTP (Google Authenticator) onboarding with QR code
- Login with password + second factor (WhatsApp OTP or Google Authenticator)
- Password reset via email with time-limited token
- Basic brute-force protection (temporary suspension after repeated failed logins)
- Language: Python (Flask) with server-rendered HTML/CSS
- Persistence: SQLite via Flask-SQLAlchemy
- Email: Flask-Mail (SMTP)
- WhatsApp messaging: UltraMSG API (requests)
- TOTP: pyotp (QR generation with qrcode)
- Create and activate a virtual environment:
python3 -m venv venv
source venv/bin/activate- Install dependencies (example list):
pip install flask flask_sqlalchemy flask_mail flask_migrate pyotp qrcode requests- Set required environment variables (recommended) or edit
app.py/config.pycarefully (do NOT commit secrets):
- SECRET_KEY (recommended to set in env rather than use config.py-generated value)
- MAIL_USERNAME (SMTP username)
- MAIL_PASSWORD (SMTP password or app-specific password)
- ULTRAMSG_INSTANCE_ID
- ULTRAMSG_API_TOKEN
- DATABASE_URL (optional; default is sqlite:///database.db)
Example using export (Linux/macOS):
export SECRET_KEY="replace_with_a_secure_value"
export MAIL_USERNAME="your-smtp-user@example.com"
export MAIL_PASSWORD="your-smtp-password"
export ULTRAMSG_INSTANCE_ID="instanceXXXX"
export ULTRAMSG_API_TOKEN="your_ultramsg_token"- Initialize the database and run the app:
python app.pyThe app will create an SQLite database file (database.db) automatically and run on http://127.0.0.1:5000 by default.
- Currently the repository contains hard-coded credentials in
app.pyandconfig.py(SMTP credentials, UltraMSG token, and a runtime-generated SECRET_KEY). Do not run the app in production with these values. Move secrets to environment variables. - There is no requirements.txt or pinned dependency file. Consider adding
requirements.txtorpyproject.tomlfor reproducible installs. - The demo uses SQLite and is not intended for production-scale deployment.
app.py— main Flask application with routes, user model, and OTP/TOTP logictemplates/— Jinja2 HTML templates for signup/login/OTP/reset flowsstatic/styles.css— styling for the UIconfig.py— generates a SECRET_KEY (currently creates a new key on each import)
- Replace hard-coded secrets with environment variable configuration
- Add a
requirements.txtor lockfile - Improve error handling and logging around external APIs (email/WhatsApp)
- Add unit/integration tests for authentication flows
If you want, I can add a requirements.txt, move configuration to env variables in the code, and open a pull request with those changes.