# TOTP End-to-End Test Proposal ## Test Objective Test ALL aspects of TOTP functionality regardless of current state (TOTP enabled or disabled). ## Test Flow ### Scenario A: TOTP Currently Enabled (Bob already enrolled) 1. **Login** with email/password - Response: `requires_totp: true` 2. **Get Secret from DB** (or use environment variable) - Since secret is encrypted/hashed in DB, we need to either: - Store it in environment/file from previous enrollment, OR - User provides it as input, OR - Use backup code from previous enrollment 3. **Generate TOTP Code** using stored secret/backup code 4. **Verify TOTP** to complete login - Endpoint: `/auth/totp/verify` - Get auth_token 5. **Check TOTP Status** - Endpoint: `/auth/totp/status` - Confirm: `totp_enabled: true` 6. **Disable TOTP** - Endpoint: `/auth/totp/disable` - Provide password 7. **Logout** 8. **Continue to Scenario B steps 2-14** ### Scenario B: TOTP Currently Disabled (or after completing Scenario A) 1. **Login** with email/password - Response: `token` (no TOTP required) 2. **Check TOTP Status** - Endpoint: `/auth/totp/status` - Confirm: `totp_enabled: false` 3. **Enroll in TOTP** - Endpoint: `/auth/totp/enroll` - Store: secret, backup_codes, provisioning_uri, qr_code 4. **Generate TOTP Code** from new secret - Use timezone-aware UTC 5. **Verify Enrollment** - Endpoint: `/auth/totp/verify-enrollment` - Provide generated code 6. **Check TOTP Status Again** - Confirm: `totp_enabled: true` - Confirm: `backup_codes_remaining: 10` - Confirm: `verified_at` is set 7. **Logout** 8. **Login** with email/password - Response: `requires_totp: true` 9. **Generate TOTP Code** from stored secret 10. **Verify TOTP** to complete login - Endpoint: `/auth/totp/verify` - Get auth_token 11. **Confirm Logged In** - Endpoint: `/auth/me` - Verify user data returned 12. **Test Backup Code** (new login) - Logout - Login with email/password - Use backup code instead of TOTP - Endpoint: `/auth/totp/verify` with `is_backup_code: true` 13. **Check Backup Codes Remaining** - Should be 9 (one consumed) 14. **Regenerate Backup Codes** - Endpoint: `/auth/totp/regenerate-backup-codes` - Provide password - Get new set of 10 codes ## Implementation Strategy ### Secret Persistence Between Test Runs **Option 1: Environment Variable** (Recommended) ```python import os # Save secret after first successful enrollment SECRET_FILE = ".totp_test_secret" if os.path.exists(SECRET_FILE): with open(SECRET_FILE) as f: data = json.load(f) known_secret = data.get("secret") known_backup_codes = data.get("backup_codes", []) else: known_secret = None known_backup_codes = [] # After enrollment, save for next run with open(SECRET_FILE, 'w') as f: json.dump({ "secret": new_secret, "backup_codes": new_backup_codes }, f) ``` **Option 2: Test Database State** - Include SQL query to fetch secret from DB (if stored in plain text for testing) - Or decrypt if encrypted **Option 3: Manual Input** - Prompt user for secret/backup code if TOTP already enabled - Less automated but more flexible ## Expected Assertions 1. ✅ Login without TOTP works when disabled 2. ✅ Enrollment generates secret, QR code, backup codes 3. ✅ Enrollment verification accepts valid TOTP code 4. ✅ TOTP status shows enabled after verification 5. ✅ Login requires TOTP when enabled 6. ✅ TOTP verification works during login 7. ✅ Backup code works for authentication 8. ✅ Backup codes decrement when used 9. ✅ Backup code regeneration works 10. ✅ TOTP disable works with correct password 11. ✅ Login works without TOTP after disabling ## Test Data Management Store in `.totp_test_data.json` (gitignored): ```json { "user": "bob@acme-corp.com", "secret": "BWAQAP55...", "backup_codes": ["code1", "code2", ...], "enrollment_date": "2026-01-14T03:12:00Z", "last_test_run": "2026-01-14T03:15:00Z" } ``` ## Error Handling - Connection errors → clear message about server not running - 401 errors → check if token/credentials are correct - TOTP code failures → check time synchronization - Backup code failures → check if already used ## Success Criteria Test passes when: 1. All 14 steps complete without errors 2. All assertions pass 3. Test can run multiple times (idempotent) 4. Works from both initial states (TOTP enabled/disabled) --- **Please review this proposal. Once approved, I'll implement it.**