TOTP Integration Guide
Implement time-based one-time passwords for offline and backup authentication.
Time-Based
Codes refresh every 30 seconds for maximum security.
Offline Capable
Works without internet connection on the user's device.
RFC 6238 Compliant
Compatible with any authenticator app.
TOTP Setup Flow
Generate a TOTP Secret
Create a unique secret for the user and store it securely.
// Generate TOTP secret for a user
const totp = await affirmid.totp.create({
userId: 'user_123',
issuer: 'Acme Inc', // Your company name
accountName: 'john@example.com' // User identifier
});
console.log(totp);
// {
// secret: 'JBSWY3DPEHPK3PXP', // Base32 encoded secret
// qrCodeUrl: 'data:image/png;base64,...',
// otpauthUrl: 'otpauth://totp/Acme:john@example.com?...'
// }Display QR Code to User
Show the QR code for the user to scan with their authenticator app.
// React component example
function TotpSetup({ qrCodeUrl, secret }) {
return (
<div>
<h2>Scan this QR code with your authenticator app</h2>
<img src={qrCodeUrl} alt="TOTP QR Code" />
{/* Manual entry fallback */}
<p>Or enter this code manually:</p>
<code>{secret}</code>
</div>
);
}Verify Initial Code
Confirm the user has set up their authenticator correctly before enabling TOTP.
// Verify the setup code
const verification = await affirmid.totp.verifySetup({
userId: 'user_123',
code: '123456' // Code entered by user
});
if (verification.valid) {
// TOTP is now active for this user
console.log('TOTP enabled successfully');
} else {
console.log('Invalid code, please try again');
}Verifying TOTP Codes
Basic Verification
// Verify a TOTP code during login
async function verifyTotpLogin(userId: string, code: string) {
const result = await affirmid.totp.verify({
userId: userId,
code: code
});
if (result.valid) {
// Code is correct - grant access
return { success: true };
} else {
// Invalid code
return {
success: false,
error: result.reason // 'invalid_code' | 'expired' | 'already_used'
};
}
}With Replay Protection
AffirmID automatically prevents code reuse. Each code can only be used once within its validity window.
// Codes are automatically tracked
const result1 = await affirmid.totp.verify({ userId, code: '123456' });
console.log(result1.valid); // true
// Same code cannot be reused
const result2 = await affirmid.totp.verify({ userId, code: '123456' });
console.log(result2.valid); // false
console.log(result2.reason); // 'already_used'Configuration Options
| Option | Default | Description |
|---|---|---|
| period | 30 | Seconds between code rotations |
| digits | 6 | Number of digits in the code |
| algorithm | SHA1 | SHA1, SHA256, or SHA512 |
| window | 1 | Number of periods to accept (before/after) |
Backup Codes
Generate one-time backup codes for users who lose access to their authenticator app.
// Generate backup codes
const backupCodes = await affirmid.totp.generateBackupCodes({
userId: 'user_123',
count: 10 // Generate 10 codes
});
console.log(backupCodes);
// {
// codes: ['ABCD-1234', 'EFGH-5678', ...],
// createdAt: '2024-01-15T12:00:00Z'
// }
// Verify a backup code
const result = await affirmid.totp.verifyBackupCode({
userId: 'user_123',
code: 'ABCD-1234'
});
// Each backup code can only be used onceImportant
Display backup codes only once during setup. Advise users to store them securely offline. Consider requiring re-authentication before generating new backup codes.
Best Practices
Verify during setup
Always verify the initial code before enabling TOTP.
Provide backup codes
Generate backup codes so users can recover access.
Show manual entry option
Some users can't scan QR codes - show the secret key.
Use as fallback
Offer TOTP when push notifications aren't available.