Skip to main content

Overview

Multi-Factor Authentication (MFA) adds an additional layer of security by requiring users to provide a second form of authentication beyond their password. SuperTokens Core implements Time-based One-Time Password (TOTP) for MFA, compatible with authenticator apps like Google Authenticator, Authy, and Microsoft Authenticator.

TOTP Implementation

TOTP is implemented in io.supertokens.totp.Totp - View source Standard: RFC 6238 (TOTP: Time-Based One-Time Password Algorithm) Algorithm: HMAC-SHA1 with 6-digit codes

Device Registration

Users can register multiple TOTP devices (e.g., multiple phones, backup devices).

Register Device

Create a new TOTP device for a user. Implementation: io.supertokens.totp.Totp.registerDevice() - View source Process:
  1. Generate a random 160-bit secret key
  2. Base32 encode the secret
  3. Create device record (unverified)
  4. Return secret for QR code generation
API Endpoint: POST /recipe/totp/device Request Body:
Response:

Secret Key Generation

Implementation: io.supertokens.totp.Totp.generateSecret() - View source

QR Code Format

TOTP URIs follow the Google Authenticator format:
Example:

Device Verification

Devices must be verified before they can be used for authentication.

Verify Device

Verify a device by validating a TOTP code. Implementation: io.supertokens.totp.Totp.verifyDevice() - View source Process:
  1. Check if device exists and is unverified
  2. Validate TOTP code against device secret
  3. Check rate limiting
  4. Mark device as verified
  5. Return verification status
API Endpoint: POST /recipe/totp/device/verify Request Body:
Response (Success):
Response (Invalid Code):

TOTP Verification

Verify TOTP codes during login or sensitive operations.

Verify Code

Implementation: io.supertokens.totp.Totp.verifyCode() - View source Validation Process:
  1. Retrieve all verified devices for user
  2. Check each device with time skew
  3. Prevent code replay attacks
  4. Enforce rate limiting
  5. Store used code with expiry
API Endpoint: POST /recipe/totp/verify Request Body:
Response (Success):
Response (Invalid):
Response (Rate Limited):

Code Verification Algorithm

Implementation: io.supertokens.totp.Totp.checkCode() - View source
Time Skew:
  • Default: ±1 period (30 seconds before/after)
  • Allows for clock drift between client and server
  • Configurable per device

Rate Limiting

Protect against brute force attacks with sophisticated rate limiting. Implementation: io.supertokens.totp.Totp.checkAndStoreCode() - View source Algorithm:
  1. Fetch all recent code attempts (valid and invalid)
  2. Count consecutive invalid attempts
  3. If max attempts reached, calculate cooldown time
  4. Block further attempts until cooldown expires
Configuration:
Rate Limit Logic:

Replay Attack Prevention

Prevent the same code from being used multiple times. Implementation:
  1. Store each used code with expiry time
  2. Check if code was previously used
  3. Reject code if still valid and previously used
  4. Expiry time = device.period × (2 × device.skew + 1)
Example:
  • Period: 30 seconds
  • Skew: 1
  • Expiry: 30 × (2 × 1 + 1) = 90 seconds
Code Storage:

Device Management

List Devices

Retrieve all TOTP devices for a user. Implementation: io.supertokens.totp.Totp.getDevices() - View source API Endpoint: GET /recipe/totp/device/list?userId={userId} Response:

Remove Device

Delete a TOTP device. Implementation: io.supertokens.totp.Totp.removeDevice() - View source API Endpoint: POST /recipe/totp/device/remove Request Body:
Process:
  1. Delete specified device
  2. If last device, delete user from TOTP system
  3. Return success

Update Device Name

Rename a TOTP device. Implementation: io.supertokens.totp.Totp.updateDeviceName() - View source API Endpoint: PUT /recipe/totp/device Request Body:

Bulk Device Status

Check TOTP status for multiple users in a single query. Implementation: io.supertokens.totp.Totp.getBulkDeviceStatus() - View source API Endpoint: POST /recipe/totp/device/status/bulk Request Body:
Response:
Return Values:
  • true: User has at least one verified TOTP device
  • false: User has devices but none are verified
  • null: User has no TOTP devices

Import Devices

Import TOTP devices from other systems. Implementation: io.supertokens.totp.Totp.createDevices() - View source API Endpoint: POST /recipe/totp/device/import Request Body:

Configuration

TOTP Settings

Device Parameters

Period:
  • Default: 30 seconds
  • Standard: 30 seconds (most compatible)
  • Range: 1-300 seconds
Skew:
  • Default: 1 (±30 seconds)
  • Recommended: 1-2
  • Higher values = more tolerance, less security
Digits:
  • Fixed: 6 digits
  • Standard for maximum compatibility

Security Considerations

Secret Storage

  • Secrets are stored in plaintext in the database
  • Protect database access with encryption at rest
  • Consider application-level encryption for secrets

Clock Synchronization

  • Server time must be accurate (use NTP)
  • Skew parameter allows for minor drift
  • Monitor server time drift

Backup Codes

  • Not implemented in core TOTP module
  • Implement at application layer
  • Store hashed like passwords

Recovery

  • Require email/SMS verification for MFA reset
  • Log all MFA changes
  • Notify users of MFA changes

Best Practices

  1. Require MFA for sensitive operations: Not just login
  2. Allow multiple devices: Users need backup devices
  3. Clear device names: Help users identify their devices
  4. Verify immediately: Prompt users to verify after registration
  5. Provide QR codes: Easier than manual entry
  6. Show recovery options: Before users lose access
  7. Rate limiting: Prevent brute force attacks
  8. Audit logs: Track MFA changes and usage
  9. User education: Explain MFA benefits and usage
  10. Test thoroughly: Especially time-sensitive code validation

Common Issues

Time Synchronization

Problem: Codes are always invalid Solution:
  • Check server time with NTP
  • Increase skew parameter temporarily
  • Verify client device time

Code Already Used

Problem: Valid code rejected as used Solution:
  • This is intentional (replay prevention)
  • Wait 30 seconds for new code
  • Increase period if users frequently retry

Rate Limiting

Problem: Users locked out after failed attempts Solution:
  • Provide clear error messages with retry time
  • Implement MFA recovery flow
  • Consider adjusting max attempts or cooldown

Multi-Tenancy

TOTP devices are tenant-specific:
  • Users in different tenants have separate devices
  • Rate limiting is per-tenant
  • Configuration can vary by tenant

Feature Flag

MFA requires the enterprise license:
Error if not enabled: