Skip to content

Conversation

@maxto024
Copy link
Contributor

@maxto024 maxto024 commented Dec 11, 2025

PR Description - MFA Implementation

🎯 Summary

Implements Multi-Factor Authentication (MFA) for enhanced login security in MindLogger Admin. Users with MFA enabled must provide a 6-digit TOTP code or recovery code after entering their credentials.

Jira Main

Jira Ticket: M2-9998

Sub Tasks Fixed:

  • Jira Ticket: M2-10194

  • Jira Ticket: M2-10195

  • Jira Ticket: M2-10196 ✨ NEW

    • Commit: 18f00e75d1840e6a33cd469a3df713a53e00668b
    • Fixed: Invalid TOTP code now shows inline error instead of redirecting to login
    • Issue: After entering invalid 6-digit verification code, user was redirected to login page with no explanation
    • Solution:
      • Shows inline "Invalid code" message with red border
      • Error clears when user edits input
      • No automatic redirects on error or session expiry
      • Added "Back to Login" link for manual navigation
      • Session persists to allow retries

🔧 Changes

Core Features

  • Conditional Login Flow: Automatically detects MFA requirement and shows appropriate UI
  • TOTP Verification: 6-digit code verification with auto-submit functionality
  • Recovery Codes: Backup authentication method with proper formatting (XXXXX-XXXXX)
  • Session Management: 5-minute MFA sessions with graceful expiry handling
  • Rate Limiting: Maximum 5 attempts with warning after 3 attempts
  • Error Handling: Inline error messages without redirects, proper internationalization

Technical Implementation

  • State Management: Separate Redux state for MFA verification (prevents interference with login state)
  • Custom Hook Pattern: useMFAVerification provides shared logic for both forms
  • Hybrid State: Local state for UI control, Redux for error display
  • API Integration: New endpoints for TOTP and recovery code verification
  • Form Validation: Yup schemas with real-time validation
  • Auto-submit: Automatic form submission when 6 digits entered
  • Session Persistence: MFA session preserved until explicit user action

Components Added

  • AuthFlow: Main authentication flow controller with session tracking
  • MFAForm: TOTP code entry form with inline error display
  • RecoveryCodeForm: Recovery code entry form with auto-formatting
  • useMFAVerification: Custom hook for verification logic
  • mfa.utils: Error mapping utilities for user-friendly messages

Bug Fixes (M2-10196)

  • ✅ Invalid verification codes show inline errors (no redirect)
  • ✅ Expired verification codes show "Session expired" error (no redirect)
  • ✅ Already used codes show appropriate error (no redirect)
  • ✅ Offline errors handled gracefully (no redirect)
  • ✅ Errors clear when user edits input
  • ✅ After 5 attempts, user can manually go back to login

Video

https://www.loom.com/share/d2bb4f21fdfe46b38b76baaf6c766d46

Screenshots

MFA Flow

|MFA TOTP Form|Invalid Code Error|Session Expired|Attempts Warning|

✅ Testing

  • Unit tests for all components
  • Custom hook tests (useMFAVerification.test.tsx)
  • Redux thunk tests for API interactions
  • Form validation and error display tests
  • Session expiry and cleanup tests
  • All tests passing (24 tests, 13 skipped for future enhancements)

🔐 Security Considerations

  • MFA tokens stored securely in Redux (not localStorage)
  • Session expires after 5 minutes with graceful handling
  • Rate limiting prevents brute force attacks (5 attempts max)
  • No sensitive data logged to console
  • Proper cleanup on unmount

🌐 Internationalization

Added translations for:

  • English (app-en.json)
  • French (app-fr.json)

Key translations:

  • Error messages: invalidCode, mfaSessionExpired, tooManyAttempts
  • UI text: confirmYourIdentity, enterVerificationCode, backToLogin

📚 Documentation

🚀 How to Test

  1. Login with MFA-enabled user (e.g., geria.test+mfa08@gmail.com)
  2. Test invalid code → see inline error (no redirect)
  3. Test session expiry (wait 5 min) → see expiry error (no redirect)
  4. Test recovery code with wrong format → see format error
  5. Test "Back to Login" link → returns to login form
  6. Test successful verification → navigates to library

⚡ Performance

  • Minimal bundle size increase (~15KB gzipped)
  • No additional API calls unless MFA is enabled
  • Efficient Redux state updates
  • Debounced auto-submit to prevent excessive API calls
  • Local state for UI prevents re-render cascades

🔄 Backwards Compatibility

  • Non-breaking change
  • Users without MFA continue to login normally
  • Existing auth tokens remain valid
  • Legacy error handling preserved

📝 Checklist

  • Code follows project style guidelines
  • Self-reviewed code
  • Added comments for complex logic
  • Updated documentation
  • No console warnings
  • Added unit tests
  • All tests passing
  • Tested on Chrome, Firefox, Safari
  • Added translations for all user-facing text
  • Fixed redirect issue (M2-10196)
  • Verified inline error display
  • Tested session expiry handling

- Add TOTP and recovery code verification flows
- Implement MFA session management with 5 minute expiry
- Add rate limiting with 5 attempt maximum
- Create reusable MFA form components with auto-submit
- Add comprehensive error handling and user feedback
- Include English and French translations
- Add unit tests for all MFA components
@aws-amplify-us-east-1
Copy link

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-2181.d2ccder08v9rmu.amplifyapp.com

@maxto024 maxto024 marked this pull request as ready for review December 12, 2025 15:54
@maxto024 maxto024 closed this Dec 16, 2025
@maxto024 maxto024 reopened this Dec 16, 2025
  - Create MFA-specific styled components separate from login styles
  - Fix container dimensions (473px width) and centering
  - Remove input masks and fix cursor positioning
  - Update all text to match design requirements
  - Remove link underlines and reposition Back button
  - Update tests to match new UI text
  - Move error formatting logic from component to Redux state to persist through re-renders
  - Add displayError field to MFAVerificationState for pre-formatted error messages
  - Fix race condition when clearing input after failed verification attempts
  - Handle "MFA session not found or expired" error for recovery codes
  - Show attempt count after 3 failed TOTP attempts (e.g., "2 attempts remaining")
  - Update tests to match new error handling approach
  - Update MFA implementation documentation
…tion validation, attempt warnings, and session-expiry errors
@divbzero divbzero self-assigned this Dec 24, 2025
@maxto024 maxto024 requested review from sricharan-varanasi and removed request for sricharan-varanasi December 29, 2025 22:23
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.

Overall looks good! Follows our general MFA design as well as OWASP recommendations.

Please see comments for a few requested changes around:

  • Deduping hasValidResult and formatRecoveryCode functions
  • Reusing components when possible instead of defining new styled components
  • Removing custom letter-spacing on recovery code <input> for consistency
  • Removing console.log debug statement

@divbzero divbzero removed their assignment Dec 31, 2025
@divbzero divbzero self-requested a review December 31, 2025 16:11
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.

Looks good!

@maxto024
Copy link
Contributor Author

maxto024 commented Jan 5, 2026

Looks good!

Thank you so much, going to merge now.

@maxto024 maxto024 merged commit e1368ef into develop Jan 5, 2026
4 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.

4 participants