Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SSE-MTECH Lab 1 — Secure Authentication System (Flask)

A complete Python/Flask implementation of Lab Assignment 1 covering all three parts.


Project Structure

flask-secure-login/
├── app.py                  ← Main Flask application (all API routes)
├── demo.py                 ← Automated demo script (run after app.py)
├── requirements.txt        ← Python dependencies
├── db/
│   ├── users.json          ← User records (auto-created on first register)
│   └── attack_log.json     ← Credential stuffing log
├── templates/
│   └── index.html          ← Web UI
└── static/
    ├── css/style.css       ← Stylesheet
    └── js/app.js           ← Frontend JavaScript

Setup & Run

# 1. Create virtual environment (recommended)
python -m venv venv
source venv/bin/activate          # Linux/Mac
venv\Scripts\activate             # Windows

# 2. Install dependencies
pip install -r requirements.txt

# 3. Start the server
python app.py

# 4. Open browser
http://localhost:5000

# 5. Run automated demo (in a second terminal, while app.py is running)
python demo.py

Part 1 — Secure Login with bcrypt

Registration

POST /api/register
Body: { "username": "alice", "password": "SecurePass@123" }
  • Password is hashed with bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
  • rounds=12 means 2¹² = 4096 bcrypt iterations (OWASP minimum)
  • The hash is stored; the plaintext is never written anywhere
  • Hash always starts with $2b$12$ confirming bcrypt + cost factor

Login

POST /api/login
Body: { "username": "alice", "password": "SecurePass@123" }
  • Verification via bcrypt.checkpw(password, stored_hash)
  • Returns generic "Invalid credentials" for both bad username and bad password (prevents user enumeration)

DB Viewer

GET /api/db

Shows all user records including the bcrypt hash — no plaintext anywhere.


Part 2 — Credential Stuffing + Rate Limiting + Lockout

Rate Limiting

  • flask-limiter limits the /api/login endpoint to 5 requests per IP per 15 minutes
  • Exceeding the limit returns HTTP 429
  • Configured with @limiter.limit("5 per 15 minutes")

Account Lockout

  • After 5 consecutive failed password attempts, the account is locked for 10 minutes
  • Lockout is per-user (not per-IP), so rotating IPs doesn't help the attacker
  • locked_until timestamp stored in DB

Attack Simulation

POST /api/attack-simulate
Body: { "target_username": "alice", "passwords": ["123456", "password", ...] }

Simulates an automated attacker cycling through a rockyou.txt-style wordlist. Attack log output:

✗ "123456"   → Wrong password. Attempts: 1/5
✗ "password" → Wrong password. Attempts: 2/5
✗ "qwerty"   → Wrong password. Attempts: 3/5
✗ "abc123"   → Wrong password. Attempts: 4/5
✗ "letmein"  → Wrong password. Attempts: 5/5 — LOCKED
🔒 "dragon"  → BLOCKED — account is locked

Part 3 — TOTP 2FA with pyotp

Setup (generate secret + QR)

POST /api/2fa/setup
Body: { "username": "alice" }
Response: { "secret": "BASE32...", "qr_code": "data:image/png;base64,...", "otpauth_url": "..." }
  • Scan the QR code in Google Authenticator
  • OTPAuth URL format: otpauth://totp/alice?secret=...&issuer=SSE-MTECH-Lab1

Enable (confirm first OTP)

POST /api/2fa/confirm
Body: { "username": "alice", "otp": "123456" }

Login with 2FA

# Step 1
POST /api/login
Body: { "username": "alice", "password": "SecurePass@123" }
Response: { "requires_2fa": true }

# Step 2 (same session)
POST /api/login/verify-otp
Body: { "otp": "123456" }
Response: { "success": true }

Security Properties

Attack Defence
Wrong OTP HMAC-SHA1 mismatch → rejected
Expired OTP valid_window=1 allows ±30s drift only
Replay attack Used OTPs tracked per 30s window → rejected
Brute force Covered by password-level lockout

API Reference

Method Path Description
POST /api/register Register a new user
POST /api/login Login (rate-limited, lockout-aware)
POST /api/login/verify-otp Submit TOTP code (2FA step 2)
POST /api/2fa/setup Generate TOTP secret + QR code
POST /api/2fa/confirm Enable 2FA after QR scan
GET /api/db View database (shows hashed passwords)
POST /api/attack-simulate Credential stuffing demo
POST /api/admin/reset-lockout Reset lockout (demo only)

References

About

Flask bcrypt pyotp TOTP 2FA

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages