Skip to content

Conversation

@sricharan-varanasi
Copy link
Contributor

@sricharan-varanasi sricharan-varanasi commented Dec 23, 2025

  • Tests for the changes have been added
  • Related documentation has been added / updated
  • For new features, QA automation engineers have been tagged
  • OSS packages added to Curious open source credit page

📝 Description

🔗 Jira Ticket M2-10254

This PR implements a comprehensive email notification system for Multi-Factor Authentication (MFA) events, providing users with real-time security alerts and awareness of authentication activities on their account.

Changes include:

  • MFA Notification Service: New MFANotificationService with 9 notification types:

    • Account locked
    • MFA enabled/disabled
    • Recovery code used
    • Last recovery code warning
    • Failed authentication attempts warning
    • Failed MFA disable attempts warning
    • Recovery codes viewed/downloaded
  • Email Templates: 9 professional HTML email templates in src/apps/shared/static/templates/mfa/:

    • Branded with MindLogger styling
    • Actionable security recommendations
    • Clear timestamp and context information
  • Request Metadata Tracking: Captures user metadata for security notifications

  • Configuration-Driven: All settings configurable via environment variables:

    • MFA__ENABLE_EMAIL_NOTIFICATIONS: Feature flag (default: true)
    • MFA__RECOVERY_CODE_COUNT: Number of codes to generate (default: 10)
    • MFA__FAILED_ATTEMPTS_WARNING_THRESHOLD: Failed attempt warning threshold (default: 5)
    • MFA__DISABLE_FAILED_ATTEMPTS_WARNING_THRESHOLD: Disable attempt warning (default: 1)
    • MFA__LAST_RECOVERY_CODE_WARNING_THRESHOLD: Low codes warning (default: 1)
  • Helper Utilities:

    • mfa_helpers.py: Request metadata extraction
    • send_recovery_code_notifications(): Centralized recovery code notification logic
  • Integration Points: Notifications integrated into:

    • TOTP enable/verify endpoints
    • MFA disable flow
    • Recovery code view/download endpoints
    • Authentication failure handling

🪤 Peer Testing

Requires pipenv shell

Test 1: MFA Enable Notification

  1. Create a new user account or use an existing test account

  2. Initiate MFA setup via POST /users/me/mfa/totp/initiate

  3. Complete MFA setup via POST /users/me/mfa/totp/verify with valid TOTP code

    Expected outcome: Receive "MFA Enabled" email with:

    • Confirmation that MFA is now active
    • Number of recovery codes generated
    • Timestamp of enablement

Test 2: Recovery Code Usage Notification

  1. Enable MFA on test account (if not already enabled)

  2. Use a recovery code to authenticate (simulate TOTP unavailability)

  3. Check email inbox

    Expected outcome: Receive "Recovery Code Used" email

Test 3: Failed Authentication Attempts Warning

  1. Enable MFA on test account

  2. Attempt MFA verification with invalid TOTP codes 5 times (or configured threshold)

    Expected outcome: Receive "Failed Authentication Attempts" warning email after threshold is reached

Test 4: MFA Disable Notification

  1. Disable MFA via POST /users/me/mfa/totp/disable/verify

  2. Check email inbox

    Expected outcome: Receive "MFA Disabled" email

Test 5: Feature Flag (Disable Notifications)

  1. Set environment variable: MFA__ENABLE_EMAIL_NOTIFICATIONS=false

  2. Restart the application

  3. Perform any MFA action (enable, disable, use recovery code, etc.)

    Expected outcome:

    • MFA functionality works normally
    • NO emails are sent

Test 6: Account Lockout Notification

  1. Enable MFA on test account

  2. Exceed global lockout threshold (default: 10 failed attempts within cooldown period)

    Expected outcome: Receive "Account Locked" CRITICAL email with:

    • Lockout duration information
    • Security recommendations
    • Timestamp of lockout

✏️ Notes

  • Email Templates Location: src/apps/shared/static/templates/mfa/ and src/apps/shared/static/subjects/mfa/
  • Configuration: All thresholds and settings use defaults from config/mfa.py but can be overridden via environment variables
  • No Breaking Changes: All new functionality, existing endpoints remain unchanged
  • Async Processing: All emails queued via RabbitMQ/Celery, non-blocking for API responses

Related Files:

  • Service: src/apps/authentication/services/mfa_notifications.py
  • Tasks: src/apps/authentication/tasks.py
  • Config: src/config/mfa.py
  • Helpers: src/apps/authentication/services/mfa_helpers.py
  • Templates: src/apps/shared/static/templates/mfa/*.html

Copy link
Contributor

@divbzero divbzero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No major concerns on this PR either. Please take a close look at lockout_until and maybe consider changing where we add current_year to templates.

Copy link
Contributor

@divbzero divbzero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good, thanks @sricharan-varanasi!

@sricharan-varanasi sricharan-varanasi merged commit 0883c56 into develop Jan 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants