Two-Factor Authentication
Complete guide to implementing and using Two-Factor Authentication (2FA) with AINative Studio.
Table of Contents
- Overview
- Getting Started
- Enabling 2FA
- Using 2FA
- Backup Codes
- Account Management
- Security Features
- Troubleshooting
- 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:
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
| 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:
- Incorrect phone number
- SMS delivery delay (wait 60 seconds)
- Phone service issues
- 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!
- Use a backup code to login
- Update your phone number
- 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}")
Related Documentation
Last Updated: December 7, 2025 Version: 1.0