# Integrated 2FA Login Flow Documentation

## 🔄 Updated Login Flow

The login endpoint now seamlessly integrates 2FA verification. Here's how it works:

## 📡 API Endpoint

### **POST /api/authenticate**

**Request Body:**
```json
{
  "email": "user@example.com",
  "password": "password123",
  "code": "123456" // Optional: 6-digit 2FA code
}
```

## 🎯 Login Scenarios

### **Scenario 1: User WITHOUT 2FA Enabled**
```json
// Request
POST /api/authenticate
{
  "email": "user@example.com",
  "password": "password123"
}

// Response
{
  "access_token": "1|abc123...",
  "user": { ... },
  "requires_2fa": false
}
```

### **Scenario 2: User WITH 2FA Enabled (No Code Provided)**
```json
// Request
POST /api/authenticate
{
  "email": "user@example.com",
  "password": "password123"
}

// Response
{
  "message": "Two-factor authentication required.",
  "requires_2fa": true,
  "user_id": 123
}
```

### **Scenario 3: User WITH 2FA Enabled (Valid Code Provided)**
```json
// Request
POST /api/authenticate
{
  "email": "user@example.com",
  "password": "password123",
  "code": "123456"
}

// Response
{
  "access_token": "1|abc123...",
  "user": { ... },
  "requires_2fa": false
}
```

### **Scenario 4: User WITH 2FA Enabled (Invalid Code)**
```json
// Request
POST /api/authenticate
{
  "email": "user@example.com",
  "password": "password123",
  "code": "000000"
}

// Response
{
  "message": "The given data was invalid.",
  "errors": {
    "code": ["Invalid two-factor authentication code."]
  }
}
```

## 🎮 Frontend Integration Flow

### **Step 1: Initial Login Attempt**
```javascript
async function login(email, password) {
  const response = await fetch('/api/authenticate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });
  
  const data = await response.json();
  
  if (data.requires_2fa) {
    // Show 2FA input modal/form
    showTwoFactorForm(data.user_id);
  } else {
    // Normal login success
    storeToken(data.access_token);
    redirectToDashboard();
  }
}
```

### **Step 2: 2FA Verification**
```javascript
async function verifyTwoFactor(userId, code) {
  const response = await fetch('/api/authenticate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ 
      email: storedEmail,
      password: storedPassword,
      code: code 
    })
  });
  
  const data = await response.json();
  
  if (data.access_token) {
    // 2FA verification successful
    storeToken(data.access_token);
    redirectToDashboard();
  } else {
    // Handle invalid 2FA code
    showErrorMessage('Invalid authentication code');
  }
}
```

## 🔄 Complete Frontend Example

```javascript
class LoginHandler {
  constructor() {
    this.tempCredentials = null;
  }

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

      const data = await response.json();

      if (data.requires_2fa) {
        // Store credentials temporarily for 2FA verification
        this.tempCredentials = { email, password };
        this.showTwoFactorModal();
      } else if (data.access_token) {
        this.handleSuccessfulLogin(data);
      } else {
        this.handleError(data);
      }
    } catch (error) {
      this.handleNetworkError(error);
    }
  }

  async handleTwoFactorVerification(code) {
    if (!this.tempCredentials) return;

    try {
      const response = await fetch('/api/authenticate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ...this.tempCredentials,
          code: code
        })
      });

      const data = await response.json();

      if (data.access_token) {
        this.handleSuccessfulLogin(data);
        this.hideTwoFactorModal();
        this.clearTempCredentials();
      } else {
        this.showTwoFactorError('Invalid authentication code');
      }
    } catch (error) {
      this.handleNetworkError(error);
    }
  }

  handleSuccessfulLogin(data) {
    localStorage.setItem('auth_token', data.access_token);
    localStorage.setItem('user', JSON.stringify(data.user));
    window.location.href = '/dashboard';
  }

  showTwoFactorModal() {
    // Show modal with 6-digit input field
    // Add countdown timer for TOTP codes
    // Include backup code option
  }

  hideTwoFactorModal() {
    // Hide 2FA modal
  }

  clearTempCredentials() {
    this.tempCredentials = null;
  }

  handleError(data) {
    // Show error messages from API
    if (data.errors) {
      Object.values(data.errors).forEach(error => {
        showErrorMessage(error[0]);
      });
    } else {
      showErrorMessage(data.message || 'Login failed');
    }
  }
}

// Usage
const loginHandler = new LoginHandler();

// Initial login
loginHandler.handleLogin('user@example.com', 'password123');

// 2FA verification (after user enters code)
loginHandler.handleTwoFactorVerification('123456');
```

## 🎯 Key Benefits

### **Seamless UX**
- Single endpoint handles both scenarios
- No separate 2FA verification endpoint needed
- Consistent response structure

### **Security**
- 2FA codes are validated server-side
- Backup codes are automatically consumed
- Temporary credentials are not stored in browser

### **Flexibility**
- Frontend can handle multiple login flows
- Supports both TOTP and backup codes
- Easy to implement progressive enhancement

## 📱 Mobile App Integration

The same flow works perfectly for mobile apps:

```swift
// iOS Example
func login(email: String, password: String, code: String? = nil) {
    let parameters = ["email": email, "password": password]
    if let code = code {
        parameters["code"] = code
    }
    
    // Make API call...
    // Handle requires_2fa response
    // Show 2FA screen if needed
}
```

```kotlin
// Android Example
fun login(email: String, password: String, code: String? = null) {
    val payload = mapOf("email" to email, "password" to password).toMutableMap()
    code?.let { payload["code"] = it }
    
    // Make API call...
    // Handle requires_2fa response
    // Show 2FA screen if needed
}
```

## 🔒 Security Considerations

1. **Rate Limiting**: Implement rate limiting on login attempts
2. **Session Management**: Clear temporary credentials after use
3. **Token Storage**: Use secure storage for auth tokens
4. **Code Validation**: Always validate 2FA codes server-side
5. **Backup Codes**: Show backup codes only once during setup

Your frontend is now ready for seamless 2FA integration! 🎉
