# Email 2FA Fallback Documentation

## 🚀 Overview

Your backend now supports email-based 2FA verification as a fallback mechanism when the authenticator app doesn't work. This provides users with an alternative way to complete 2FA verification.

## 📋 Available Endpoints

### **1. Send 2FA Code via Email**
```
POST /api/2fa/send-email-code
```

**Request Body:**
```json
{
  "email": "user@example.com",
  "user_id": 123  // Optional, can use email instead
}
```

**Response:**
```json
{
  "success": true,
  "message": "2FA code sent to your email",
  "expires_in": 600
}
```

### **2. Verify Email 2FA Code**
```
POST /api/2fa/verify-email-code
```

**Request Body:**
```json
{
  "email": "user@example.com",
  "code": "123456",
  "user_id": 123  // Optional
}
```

**Response:**
```json
{
  "success": true,
  "message": "Email 2FA verified successfully",
  "user_id": 123,
  "email": "user@example.com"
}
```

### **3. Fallback Authentication**
```
POST /api/authenticate-fallback
```

**Request Body:**
```json
{
  "email": "user@example.com",
  "password": "password123",
  "code": "123456",
  "method": "email"  // or "recovery"
}
```

**Response:**
```json
{
  "access_token": "token_here",
  "user": { ... },
  "requires_2fa": false,
  "method_used": "email"
}
```

### **4. Universal Fallback Verification**
```
POST /api/2fa/fallback-verify
```

**Request Body:**
```json
{
  "email": "user@example.com",
  "code": "123456",
  "method": "email"  // or "recovery"
}
```

**Response:**
```json
{
  "success": true,
  "message": "Fallback 2FA verified successfully",
  "user_id": 123,
  "method_used": "email"
}
```

## 🎯 Frontend Integration

### **JavaScript Implementation:**

```javascript
class TwoFactorAuth {
  // Send email 2FA code
  async sendEmailCode(email, userId = null) {
    try {
      const response = await fetch('/api/2fa/send-email-code', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: email,
          user_id: userId
        })
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || 'Failed to send code');
      }
      
      return data;
    } catch (error) {
      console.error('Failed to send email code:', error);
      throw error;
    }
  }

  // Verify email 2FA code
  async verifyEmailCode(email, code, userId = null) {
    try {
      const response = await fetch('/api/2fa/verify-email-code', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: email,
          code: code,
          user_id: userId
        })
      });

      const data = await response.json();
      
      if (!response.ok) {
        throw new Error(data.message || 'Invalid code');
      }
      
      return data;
    } catch (error) {
      console.error('Failed to verify email code:', error);
      throw error;
    }
  }

  // Authenticate with fallback
  async authenticateWithFallback(email, password, code, method) {
    try {
      const response = await fetch('/api/authenticate-fallback', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: email,
          password: password,
          code: code,
          method: method
        })
      });

      const data = await response.json();
      
      if (!response.ok) {
        if (data.errors) {
          throw new Error(this.formatValidationErrors(data.errors));
        }
        throw new Error(data.message || 'Authentication failed');
      }
      
      return data;
    } catch (error) {
      console.error('Fallback authentication failed:', error);
      throw error;
    }
  }

  formatValidationErrors(errors) {
    return Object.values(errors).flat().join(', ');
  }
}
```

### **React Component Example:**

```javascript
import React, { useState } from 'react';

function TwoFactorFallback({ email, onBack, onSuccess }) {
  const [method, setMethod] = useState('email');
  const [code, setCode] = useState('');
  const [loading, setLoading] = useState(false);
  const [codeSent, setCodeSent] = useState(false);
  const [error, setError] = useState('');
  const [timeLeft, setTimeLeft] = useState(600);

  const twoFactor = new TwoFactorAuth();

  const sendCode = async () => {
    setLoading(true);
    setError('');
    
    try {
      await twoFactor.sendEmailCode(email);
      setCodeSent(true);
      startCountdown();
    } catch (error) {
      setError(error.message);
    } finally {
      setLoading(false);
    }
  };

  const verifyCode = async () => {
    setLoading(true);
    setError('');
    
    try {
      const result = await twoFactor.verifyEmailCode(email, code);
      onSuccess(result);
    } catch (error) {
      setError(error.message);
    } finally {
      setLoading(false);
    }
  };

  const startCountdown = () => {
    const timer = setInterval(() => {
      setTimeLeft((prev) => {
        if (prev <= 1) {
          clearInterval(timer);
          setCodeSent(false);
          return 600;
        }
        return prev - 1;
      });
    }, 1000);
  };

  const formatTime = (seconds) => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins}:${secs.toString().padStart(2, '0')}`;
  };

  return (
    <div className="two-factor-fallback">
      <h3>Two-Factor Authentication Fallback</h3>
      
      <div className="method-selector">
        <button 
          className={method === 'email' ? 'active' : ''}
          onClick={() => setMethod('email')}
        >
          📧 Email Code
        </button>
        <button 
          className={method === 'recovery' ? 'active' : ''}
          onClick={() => setMethod('recovery')}
        >
          🔑 Recovery Code
        </button>
      </div>

      {method === 'email' && (
        <div className="email-method">
          {!codeSent ? (
            <div>
              <p>Send a 6-digit verification code to your email:</p>
              <p className="email-address">{email}</p>
              <button 
                onClick={sendCode}
                disabled={loading}
                className="btn btn-primary"
              >
                {loading ? 'Sending...' : 'Send Code'}
              </button>
            </div>
          ) : (
            <div>
              <p>Enter the 6-digit code sent to your email:</p>
              <input
                type="text"
                value={code}
                onChange={(e) => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                placeholder="123456"
                maxLength="6"
                className="code-input"
              />
              <div className="timer">
                Code expires in: {formatTime(timeLeft)}
              </div>
              <button 
                onClick={verifyCode}
                disabled={loading || code.length !== 6}
                className="btn btn-primary"
              >
                {loading ? 'Verifying...' : 'Verify'}
              </button>
              <button 
                onClick={() => setCodeSent(false)}
                className="btn btn-secondary"
              >
                Resend Code
              </button>
            </div>
          )}
        </div>
      )}

      {method === 'recovery' && (
        <div className="recovery-method">
          <p>Enter one of your 8-character recovery codes:</p>
          <input
            type="text"
            value={code}
            onChange={(e) => setCode(e.target.value.toUpperCase().slice(0, 8))}
            placeholder="ABCD1234"
            maxLength="8"
            className="code-input"
          />
          <button 
            onClick={verifyCode}
            disabled={loading || code.length !== 8}
            className="btn btn-primary"
          >
            {loading ? 'Verifying...' : 'Use Recovery Code'}
          </button>
        </div>
      )}

      {error && <div className="error">{error}</div>}
      
      <button onClick={onBack} className="btn btn-link">
        ← Back to regular 2FA
      </button>
    </div>
  );
}
```

### **CSS Styling:**

```css
.two-factor-fallback {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.method-selector {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.method-selector button {
  flex: 1;
  padding: 10px;
  border: 2px solid #ddd;
  background: #f8f9fa;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
}

.method-selector button.active {
  border-color: #007bff;
  background: #007bff;
  color: white;
}

.email-address {
  font-family: monospace;
  background: #f8f9fa;
  padding: 8px;
  border-radius: 4px;
  margin: 10px 0;
}

.code-input {
  width: 100%;
  padding: 12px;
  font-size: 18px;
  text-align: center;
  letter-spacing: 4px;
  border: 2px solid #ddd;
  border-radius: 6px;
  margin: 10px 0;
}

.timer {
  text-align: center;
  color: #666;
  font-size: 14px;
  margin: 10px 0;
}

.error {
  background: #f8d7da;
  color: #721c24;
  padding: 10px;
  border-radius: 4px;
  margin: 10px 0;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  margin: 5px;
}

.btn-primary {
  background: #007bff;
  color: white;
}

.btn-secondary {
  background: #6c757d;
  color: white;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
```

## 📧 Email Template

The system sends a beautifully formatted HTML email with:

- **Professional design** with gradient code display
- **Clear instructions** for users
- **Security warnings** about code sharing
- **Expiration information** (10 minutes)
- **App branding** with your app name

## 🔧 Configuration

### **SMTP Settings (in .env):**
```env
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourapp.com
MAIL_FROM_NAME="${APP_NAME}"
```

### **Cache Configuration:**
Email codes are stored in Laravel's cache for 10 minutes. Make sure your cache driver is configured in `config/cache.php`.

## 🧪 Testing

Run the comprehensive test suite:
```bash
php artisan test tests/Feature/EmailTwoFactorTest.php
```

**Test Coverage:**
- ✅ Send email code
- ✅ Verify email code
- ✅ Code expiration
- ✅ Invalid code rejection
- ✅ Fallback authentication
- ✅ Recovery code fallback
- ✅ Error handling
- ✅ Validation

## 🎯 Use Cases

### **1. Lost Authenticator App**
User can't access their authenticator app:
1. Click "Can't access your authenticator?"
2. Choose "Send code to email"
3. Enter received 6-digit code
4. Complete login

### **2. Backup Method**
When authenticator app fails:
1. Use email code as primary fallback
2. Use recovery codes as secondary fallback
3. Both methods work independently

### **3. Testing Environment**
Developers can test 2FA without mobile apps:
1. Enable 2FA on test account
2. Use email codes for testing
3. Avoid app setup complications

## 🔒 Security Features

### **Code Security:**
- **6-digit random codes** (000000-999999)
- **10-minute expiration** automatically
- **Single-use codes** (deleted after verification)
- **Rate limiting** (implement as needed)

### **Email Security:**
- **Secure SMTP** with TLS encryption
- **No code storage** in email logs
- **Professional design** prevents phishing
- **Clear security warnings**

### **Cache Security:**
- **Temporary storage** only
- **Automatic cleanup** on expiration
- **User-specific keys** prevent conflicts

## 🚀 Benefits

### **User Experience:**
- **Multiple fallback options** for reliability
- **Clear instructions** and visual feedback
- **Professional email design** builds trust
- **Quick verification** process

### **Developer Experience:**
- **Simple API** with clear responses
- **Comprehensive testing** included
- **Flexible implementation** options
- **Well-documented** endpoints

### **Security:**
- **No single point of failure**
- **Time-limited codes** prevent abuse
- **Multiple verification methods**
- **Secure code generation**

Your 2FA system now provides robust fallback options ensuring users can always access their accounts! 🎉
