Description
During multi-factor authentication (MFA) verification in backend/app/routers/mfa.py, the server verifies whether the 6-digit TOTP code matches the current 30-second time step. Because the server allows a +/- 1 time step drift window and does not record used tokens, an intercepted TOTP code can be replayed multiple times within the 90-second validity window.
Steps to Reproduce
- Generate a valid 6-digit TOTP code.
- Send
POST /api/v1/auth/mfa/verify with the code. Verification succeeds.
- Immediately send the exact same code in a second request within 15 seconds.
- Second request succeeds instead of being rejected as already consumed.
Expected Behavior
- Backend: When a TOTP code is verified successfully, store
mfa_used:{user_id}:{totp_code} in Redis with an expiration of 90 seconds. Reject any incoming verification matching an active cached key.
Implementation Hints
Backend (backend/app/routers/mfa.py):
@router.post("/verify", response_model=TokenResponse)
async def verify_mfa_code(
payload: MFAVerifyRequest,
db: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis)
):
cache_key = f"mfa_used:{payload.user_id}:{payload.code}"
if await redis.exists(cache_key):
raise HTTPException(status_code=400, detail="MFA code has already been used. Please wait for the next token.")
is_valid = verify_totp(payload.user_id, payload.code)
if not is_valid:
raise HTTPException(status_code=400, detail="Invalid MFA code")
await redis.setex(cache_key, 90, "1")
return generate_auth_session(payload.user_id)
Affected Files
- backend/app/routers/mfa.py
- backend/app/core/security.py
- backend/app/core/cache.py
Labels
type:bug, level:advanced, GSSoC-26
Description
During multi-factor authentication (MFA) verification in
backend/app/routers/mfa.py, the server verifies whether the 6-digit TOTP code matches the current 30-second time step. Because the server allows a +/- 1 time step drift window and does not record used tokens, an intercepted TOTP code can be replayed multiple times within the 90-second validity window.Steps to Reproduce
POST /api/v1/auth/mfa/verifywith the code. Verification succeeds.Expected Behavior
mfa_used:{user_id}:{totp_code}in Redis with an expiration of 90 seconds. Reject any incoming verification matching an active cached key.Implementation Hints
Backend (
backend/app/routers/mfa.py):Affected Files
Labels
type:bug, level:advanced, GSSoC-26