---
title: "Two-Factor Authentication"
description: "Set up and manage 2FA for enhanced security"
canonical: "https://docs.ainative.studio/docs/guides/two-factor-auth"
last-updated: "2026-09-23T01:51:08.820Z"
---

# Two-Factor Authentication

Source: https://docs.ainative.studio/docs/guides/two-factor-auth

> Set up and manage 2FA for enhanced security

Complete guide to implementing and using Two-Factor Authentication (2FA) with AINative Studio.

## Table of Contents

1. [Overview](#overview)
2. [Getting Started](#getting-started)
3. [Enabling 2FA](#enabling-2fa)
4. [Using 2FA](#using-2fa)
5. [Backup Codes](#backup-codes)
6. [Account Management](#account-management)
7. [Security Features](#security-features)
8. [Troubleshooting](#troubleshooting)
9. [Best Practices](#best-practices)

---

## Overview

AINative Studio's 2FA system provides enterprise-grade security with:

✅ **SMS-Based Verification** - 6-digit codes sent via SMS
✅ **10 Backup Codes** - For account recovery
✅ **Account Lockout Protection** - Auto-lock after 5 failed attempts
✅ **Code Expiration** - Codes expire after 5 minutes
✅ **Phone Number Encryption** - Phone numbers encrypted at rest
✅ **Session Management** - Revoke all 2FA sessions

### Security Features

| Feature | Description |
|---------|-------------|
| **Rate Limiting** | 10 attempts per minute |
| **Account Lockout** | 5 failed attempts = 30 min lockout |
| **Code Expiration** | Codes valid for 5 minutes |
| **Backup Codes** | One-time use, hashed after creation |
| **Phone Encryption** | AES-256 encryption |

---

## Getting Started

### Prerequisites

- Active AINative Studio account
- Access to phone for SMS reception
- Phone number in E.164 format

### Phone Number Format

Phone numbers must be in **E.164 format**:

```
+[country code][number]
```

**Examples:**
- US: `+14155552671`
- UK: `+447911123456`
- Germany: `+4930123456789`
- Japan: `+819012345678`

---

## Enabling 2FA

### Step 1: Enable 2FA

**Request:**
```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/enable \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155552671"
  }'
```

**Response:**
```json
{
  "success": true,
  "message": "Two-factor authentication enabled successfully",
  "backup_codes": [
    "A1B2C3D4E5",
    "F6G7H8I9J0",
    "K1L2M3N4O5",
    "P6Q7R8S9T0",
    "U1V2W3X4Y5",
    "Z6A7B8C9D0",
    "E1F2G3H4I5",
    "J6K7L8M9N0",
    "O1P2Q3R4S5",
    "T6U7V8W9X0"
  ]
}
```

### Step 2: Save Backup Codes

⚠️ **CRITICAL:** Backup codes are shown **only once**! Save them securely:

```python
import json

def save_backup_codes(codes, filename="backup_codes.json"):
    """Save backup codes to encrypted file"""
    data = {
        "created_at": datetime.utcnow().isoformat(),
        "codes": codes,
        "used": []
    }

    # Save to secure location
    with open(filename, 'w') as f:
        json.dump(data, f, indent=2)

    print(f"✅ Backup codes saved to {filename}")
    print("⚠️  Store this file in a secure location!")
```

### Step 3: Test 2FA

Request a test code:

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/send-code \
  -H "Authorization: Bearer $TOKEN"
```

Check your phone for the SMS code!

---

## Using 2FA

### Login Flow with 2FA

#### Step 1: Initial Login

```bash
curl -X POST https://api.ainative.io/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "your-password"
  }'
```

**Response (2FA Required):**
```json
{
  "two_fa_required": true,
  "user_id": "123e4567-e89b-12d3-a456-426614174000",
  "message": "Verification code sent to your phone"
}
```

#### Step 2: Enter SMS Code

Check your phone for the 6-digit code, then verify:

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/verify \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "123e4567-e89b-12d3-a456-426614174000",
    "code": "123456"
  }'
```

**Response (Success):**
```json
{
  "success": true,
  "message": "Verification code is valid",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "locked": false
}
```

#### Step 3: Use Access Token

```bash
curl -X GET https://api.ainative.io/api/v1/users/profile \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
```

### Python Implementation

```python
class TwoFactorAuthClient:
    def __init__(self, base_url):
        self.base_url = base_url
        self.token = None

    def login_with_2fa(self, email, password):
        """Complete 2FA login flow"""
        # Step 1: Initial login
        response = requests.post(
            f"{self.base_url}/api/v1/auth/login",
            json={"email": email, "password": password}
        )
        data = response.json()

        if data.get("two_fa_required"):
            print("📱 SMS code sent to your phone")

            # Step 2: Get code from user
            code = input("Enter 6-digit code: ")

            # Step 3: Verify code
            verify_response = requests.post(
                f"{self.base_url}/api/v1/auth/2fa/verify",
                json={
                    "user_id": data["user_id"],
                    "code": code
                }
            )
            verify_data = verify_response.json()

            if verify_data["success"]:
                self.token = verify_data["access_token"]
                print("✅ Login successful!")
                return self.token
            else:
                print("❌ Invalid code")
                return None
        else:
            # No 2FA required
            self.token = data["access_token"]
            return self.token

## Usage
client = TwoFactorAuthClient("https://api.ainative.io")
token = client.login_with_2fa("user@example.com", "password")
```

---

## Backup Codes

### What Are Backup Codes?

Backup codes are **one-time use** recovery codes that allow you to access your account if:
- You lose your phone
- Can't receive SMS
- Phone number changes

### Using a Backup Code

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/backup-codes/verify \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "123e4567-e89b-12d3-a456-426614174000",
    "backup_code": "A1B2C3D4E5"
  }'
```

**Response:**
```json
{
  "success": true,
  "message": "Backup code verified successfully",
  "remaining_codes": 9
}
```

⚠️ **Important:** Backup code is consumed (deleted) after use!

### Check Remaining Codes

```bash
curl -X GET https://api.ainative.io/api/v1/auth/2fa/backup-codes \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "count": 8,
  "last_generated": "2025-12-07T10:00:00Z"
}
```

### Generate New Backup Codes

⚠️ **Warning:** This invalidates ALL previous backup codes!

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/backup-codes/generate \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "current_code": "123456"
  }'
```

**Response:**
```json
{
  "success": true,
  "message": "New backup codes generated successfully",
  "backup_codes": [
    "X1Y2Z3A4B5",
    "C6D7E8F9G0",
    ...
  ]
}
```

---

## Account Management

### Check 2FA Status

```bash
curl -X GET https://api.ainative.io/api/v1/auth/2fa/status \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "enabled": true,
  "phone_number": "****2671",
  "verified_at": "2025-12-07T10:00:00Z",
  "backup_codes_remaining": 10,
  "is_locked": false,
  "lockout_until": null
}
```

### Update Phone Number

```bash
curl -X PUT https://api.ainative.io/api/v1/auth/2fa/phone \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "new_phone_number": "+14155552672",
    "verification_code": "123456"
  }'
```

**Requirements:**
- Must provide current 2FA code
- New phone number must be valid E.164 format

### Disable 2FA

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/disable \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "verification_code": "123456"
  }'
```

**Alternative (using backup code):**
```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/disable \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "backup_code": "A1B2C3D4E5"
  }'
```

⚠️ **Warning:** This removes all 2FA protection from your account!

### Revoke All 2FA Sessions

If you suspect unauthorized access:

```bash
curl -X DELETE https://api.ainative.io/api/v1/auth/2fa/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "verification_code": "123456"
  }'
```

**Response:**
```json
{
  "success": true,
  "message": "All 2FA sessions revoked successfully",
  "sessions_revoked": 3
}
```

This invalidates all active verification codes and forces re-verification on next login.

---

## Security Features

### Account Lockout Protection

After **5 failed verification attempts**, your account is locked for **30 minutes**.

#### Check Lockout Status

```bash
curl -X GET https://api.ainative.io/api/v1/auth/2fa/attempts \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "failed_attempts": 2,
  "locked_until": null,
  "is_locked": false
}
```

#### Admin Unlock (Admin Only)

If legitimately locked out, contact support or have admin unlock:

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/unlock \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "123e4567-e89b-12d3-a456-426614174000"
  }'
```

### Code Expiration

- **Verification codes expire after 5 minutes**
- Request a new code if expired:

```bash
curl -X POST https://api.ainative.io/api/v1/auth/2fa/send-code \
  -H "Authorization: Bearer $TOKEN"
```

### Rate Limiting

| Endpoint | Limit |
|----------|-------|
| Enable/Disable 2FA | 3 requests/hour |
| Send Code | 5 requests/hour |
| Verify Code | 10 requests/minute |
| Generate Backup Codes | 3 requests/hour |

---

## Troubleshooting

### Not Receiving SMS Codes

**Possible Causes:**
1. Incorrect phone number
2. SMS delivery delay (wait 60 seconds)
3. Phone service issues
4. Rate limit exceeded

**Solutions:**
```bash
## 1. Check your phone number
curl -X GET https://api.ainative.io/api/v1/auth/2fa/status \
  -H "Authorization: Bearer $TOKEN"

## 2. Update phone number if incorrect
curl -X PUT https://api.ainative.io/api/v1/auth/2fa/phone \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "new_phone_number": "+14155552671",
    "verification_code": "use_backup_code_here"
  }'

## 3. Use backup code as fallback
curl -X POST https://api.ainative.io/api/v1/auth/2fa/verify \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "your-user-id",
    "backup_code": "A1B2C3D4E5"
  }'
```

### Account Locked

**Error:** "Account locked due to too many failed attempts"

**Solution:** Wait 30 minutes or contact support

```bash
## Check lockout status
curl -X GET https://api.ainative.io/api/v1/auth/2fa/attempts \
  -H "Authorization: Bearer $TOKEN"
```

### Lost Phone

**Solution:** Use backup codes!

1. Use a backup code to login
2. Update your phone number
3. Generate new backup codes

```python
def recover_account_with_backup_code(backup_code):
    """Recover account and update phone number"""
    # Step 1: Login with backup code
    response = requests.post(
        "https://api.ainative.io/api/v1/auth/2fa/backup-codes/verify",
        json={
            "user_id": "your-user-id",
            "backup_code": backup_code
        }
    )

    if response.json()["success"]:
        # Step 2: Get access token
        token = login_normal()  # Regular login flow

        # Step 3: Update phone number
        update_phone(token, new_phone="+14155552672")

        # Step 4: Generate new backup codes
        new_codes = generate_backup_codes(token)
        save_backup_codes(new_codes)

        print("✅ Account recovered successfully!")
```

### All Backup Codes Used

**Solution:** Contact support at support@ainative.io

Provide:
- Account email
- Proof of identity
- Reason for lockout

---

## Best Practices

### 1. Save Backup Codes Securely

✅ **DO:**
- Store in password manager (1Password, LastPass, Bitwarden)
- Print and store in safe place
- Save encrypted file in secure location

❌ **DON'T:**
- Email to yourself
- Save in plain text on computer
- Share with anyone

### 2. Keep Phone Number Updated

```python
## Check and update phone number regularly
def verify_phone_number(client):
    status = client.get_2fa_status()
    print(f"Current phone: {status['phone_number']}")

    if input("Is this correct? (y/n): ").lower() != 'y':
        new_phone = input("Enter new phone (+country code): ")
        client.update_phone_number(new_phone)
```

### 3. Monitor Failed Attempts

```python
def check_security_status(client):
    """Regular security check"""
    attempts = client.get_attempts_status()

    if attempts['failed_attempts'] > 0:
        print(f"⚠️  Warning: {attempts['failed_attempts']} failed login attempts")

    if attempts['is_locked']:
        print(f"🔒 Account locked until {attempts['locked_until']}")
```

### 4. Use Backup Codes Wisely

- Only use when absolutely necessary
- Regenerate after using several codes
- Never use all codes without generating new ones

### 5. Regular Backup Code Rotation

```python
def rotate_backup_codes_quarterly(client):
    """Rotate backup codes every 3 months"""
    # Get current 2FA code
    code = input("Enter current 2FA code: ")

    # Generate new codes
    result = client.generate_backup_codes(code)

    # Save securely
    save_backup_codes(result['backup_codes'])

    print(f"✅ Generated {len(result['backup_codes'])} new backup codes")
```

### 6. Enable for All Accounts

```python
def enable_2fa_for_team(admin_client, team_members):
    """Enforce 2FA for all team members"""
    for member in team_members:
        if not member.has_2fa_enabled():
            send_2fa_reminder_email(member)
            log_security_event(f"2FA not enabled: {member.email}")
```

---

## Related Documentation

- [Quick Start Guide](/docs/getting-started/quick-start)
- [API Reference](/docs/api/overview)
- [Notification System Guide](/docs/guides/notifications)
- [Error Codes](/docs/api/errors)

---

**Last Updated:** December 7, 2025
**Version:** 1.0
