Files
gatehouse-api/TOTP_TEST_PROPOSAL.md
T
2026-01-14 18:06:26 +10:30

172 lines
4.5 KiB
Markdown

# 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.**