TOTP Plugin
A plugin for implementing TOTP-based two-factor authentication.
Overview
The TOTP plugin provides Time-based One-Time Password (TOTP) authentication and backup codes for implementing two-factor authentication (2FA) in your application. This plugin enables users to secure their accounts with authenticator apps like Google Authenticator, Microsoft Authenticator, or Authy, along with backup codes for account recovery.
Features
- TOTP Generation & Verification — Supports standard TOTP algorithm with configurable digit count and period
- Backup Codes — Automatically generate backup codes for account recovery
- Trusted Devices — Option to trust devices to skip TOTP verification on subsequent logins
- Event Hooks — Integration with the event bus for custom actions on TOTP events
- Configurable Settings — Customizable expiry times, cookie settings, and security options
Configuration
Standalone Mode:
[totp]
enabled = true
skip_verification_on_enable = false # Skip password verification on enable
backup_code_count = 10 # Number of backup codes to generate (default: 10)
trusted_device_duration = "720h" # How long to trust a device (30 days default)
trusted_devices_auto_cleanup = true # Automatically clean up expired trusted devices (default: false)
trusted_devices_cleanup_interval = "1h" # Interval for cleaning up expired trusted devices (default: 1 hour)
pending_token_expiry = "5m" # Expiry time for pending token (default: 5 minutes)
secure_cookie = true # Use secure flag on cookies (set to true in production)
same_site = "lax" # SameSite cookie policy (lax, strict, none)Library Mode:
import (
totpplugin "github.com/Authula/authula/plugins/totp"
totpplugintypes "github.com/Authula/authula/plugins/totp/types"
)
totpplugin.New(totpplugintypes.TOTPPluginConfig{
Enabled: true,
SkipVerificationOnEnable: false,
BackupCodeCount: 10,
TrustedDeviceDuration: 30 * 24 * time.Hour,
TrustedDevicesAutoCleanup: true,
TrustedDevicesCleanupInterval: 1 * time.Hour,
PendingTokenExpiry: 5 * time.Minute,
SecureCookie: true,
SameSite: "lax",
})NOTE: Make sure to set the AppName in your config.toml in standalone mode or in your AuthConfig in library mode, as it is used in the TOTP URI for authenticator apps.
API Reference
| HTTP Method | Route Path | Description |
|---|---|---|
POST | /totp/enable | Enable TOTP for user |
POST | /totp/disable | Disable TOTP for user |
GET | /totp/get-uri | Get TOTP URI |
POST | /totp/verify | Verify TOTP code during login |
POST | /totp/verify-backup-code | Verify backup code during login |
POST | /totp/generate-backup-codes | Generate new backup codes |
Authentication Notes
- Authenticated endpoints (
enable,disable,get-uri,generate-backup-codes): Standard authentication required. User must be authenticated via session or other auth mechanism. - Pending-token endpoints (
verify,verify-backup-code): Standard authentication NOT required. These routes require a valid TOTP pending token cookie set by the initial authentication attempt.
Endpoint Details
POST /totp/enable:
No request body required.
Response:
{
"totp_uri": "otpauth://totp/user@example.com?secret=ABCXYZ...&issuer=MyApp",
"backup_codes": ["aBcXyZ", ...]
}POST /totp/disable:
No request body required.
Response:
{
"message": "..."
}GET /totp/get-uri:
Response:
{
"totp_uri": "otpauth://totp/user@example.com?secret=ABCXYZ...&issuer=MyApp"
}POST /totp/verify:
Request:
{
"code": "123456",
"trust_device": true
}code: (Required) The 6-digit TOTP code to verifytrust_device: (Optional) If true, marks the device as trusted to skip TOTP verification on future logins for the configured duration
Response:
{
"user": {
/* ... */
},
"session": {
/* ... */
}
}POST /totp/verify-backup-code:
Request:
{
"code": "3oz4vtq7ci2n",
"trust_device": true
}code: (Required) The backup code to verify. Backup codes are single-use and will be invalidated after successful verification.trust_device: (Optional) If true, marks the device as trusted to skip TOTP verification on future logins for the configured duration
Response:
{
"user": {
/* ... */
},
"session": {
/* ... */
}
}POST /totp/generate-backup-codes:
No request body required.
Response:
{
"backup_codes": ["aBcXyZ", ...]
}Database Schema
Table: totp
| Field | Type | Key | Description |
|---|---|---|---|
id | string | PK | Unique identifier for the TOTP record |
user_id | string | FK | Reference to the user |
secret | string | - | Encrypted TOTP secret key |
backup_codes | string | - | Serialized hashed backup codes |
enabled | boolean | - | Whether TOTP is enabled |
created_at | timestamp | - | Record creation time |
updated_at | timestamp | - | Record last update time |
Table: trusted_devices
| Field | Type | Key | Description |
|---|---|---|---|
id | string | PK | Unique identifier for the trusted device |
user_id | string | FK | Reference to the user |
token | string | - | Hashed device trust token |
user_agent | string | - | Device user agent |
expires_at | timestamp | - | When the device trust expires |
created_at | timestamp | - | Record creation time |
Migrations are automatically handled when the plugin is initialized.
Plugin Capabilities
This plugin has the following hooks and capabilities:
totp.intercept— Intercepts authentication flow by setting the user a pending token cookie and returning a simple JSON response indicating a TOTP redirection. The client can then check for this response and redirect the user to the appropriate TOTP verification page.
Events
The TOTP plugin emits events that can be used to trigger custom business logic or integrate with other plugins via the event bus.
Event Hooks
The TOTP plugin emits events for the following operations:
totp.enabled— Fired when TOTP is enabled for a usertotp.disabled— Fired when TOTP is disabled for a usertotp.verified— Fired when a TOTP code is successfully verifiedtotp.backup_code_used— Fired when a backup code is usedtotp.device_trusted— Fired when a device is marked as trusted
These events can be subscribed to via the event bus for logging, analytics, or custom business logic.
Route Mappings
When using the TOTP plugin, keep /totp/verify and /totp/verify-backup-code accessible to the pending-token flow (do not force authentication on these routes).
Security Recommendations
- Secure Cookies — In production, always set
secure_cookie = trueto ensure cookies are only sent over HTTPS. - Pending Token Expiry — The pending token used to access verify routes expires in 5 minutes by default. Configure based on your security requirements.
- Backup Codes — Store backup codes securely. They are single-use and provide account recovery.
- Trusted Devices — Use appropriate
trusted_device_durationvalues. Shorter durations increase security but require more frequent TOTP verification. - Password Verification — Set
skip_verification_on_enable = falseto require password verification when enabling TOTP.
Client Plugin
If you're using the Authula SDK, add the plugin to the SDK like so:
import { createClient } from "authula";
import { TOTPPlugin } from "authula/plugins";
export const authulaClient = createClient({
url: "http://localhost:8080/auth",
plugins: [
// other plugins...
new TOTPPlugin(),
],
});