Skip to main content

Two-Factor Authentication

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

Table of Contents

  1. Overview
  2. Getting Started
  3. Enabling 2FA
  4. Using 2FA
  5. Backup Codes
  6. Account Management
  7. Security Features
  8. Troubleshooting
  9. 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

FeatureDescription
Rate Limiting10 attempts per minute
Account Lockout5 failed attempts = 30 min lockout
Code ExpirationCodes valid for 5 minutes
Backup CodesOne-time use, hashed after creation
Phone EncryptionAES-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:

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:

{
"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:

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:

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

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):

{
"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:

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):

{
"success": true,
"message": "Verification code is valid",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"locked": false
}

Step 3: Use Access Token

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

Python Implementation

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

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:

{
"success": true,
"message": "Backup code verified successfully",
"remaining_codes": 9
}

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

Check Remaining Codes

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

Response:

{
"count": 8,
"last_generated": "2025-12-07T10:00:00Z"
}

Generate New Backup Codes

⚠️ Warning: This invalidates ALL previous backup codes!

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:

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

Account Management

Check 2FA Status

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

Response:

{
"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

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

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):

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:

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:

{
"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

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

Response:

{
"failed_attempts": 2,
"locked_until": null,
"is_locked": false
}

Admin Unlock (Admin Only)

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

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:
curl -X POST https://api.ainative.io/api/v1/auth/2fa/send-code \
-H "Authorization: Bearer $TOKEN"

Rate Limiting

EndpointLimit
Enable/Disable 2FA3 requests/hour
Send Code5 requests/hour
Verify Code10 requests/minute
Generate Backup Codes3 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:

# 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

# 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
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

# 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

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

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

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}")


Last Updated: December 7, 2025 Version: 1.0