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