| path | docs/api/Authentication_2FA_API.mdx | |||||
|---|---|---|---|---|---|---|
| title | Two-Factor Authentication API | |||||
| description | Complete API reference for 2FA setup, verification, and management endpoints in SveltyCMS. | |||||
| order | 2 | |||||
| icon | mdi:shield-lock | |||||
| author | admin | |||||
| created | 2025-10-05 | |||||
| updated | 2025-10-05 | |||||
| tags |
|
This document provides a complete reference for all Two-Factor Authentication (2FA) API endpoints in SveltyCMS. The 2FA system uses Time-based One-Time Passwords (TOTP) compatible with authenticator apps like Google Authenticator, Authy, and 1Password.
The 2FA implementation uses quantum-resistant cryptography:
- Backup codes: Hashed with Argon2id (memory-hard, quantum-resistant)
- TOTP secrets: Stored with AES-256-GCM encryption (128-bit quantum security)
- SHA-256 hashing: Maintains security even with Grover's algorithm
- No RSA/ECC: Avoids public-key crypto vulnerable to Shor's algorithm
- Security timeline: Secure against quantum computers for 15-30+ years
While TOTP itself uses SHA-1 (TOTP standard), the secret storage and backup code hashing use quantum-resistant algorithms. See Quantum Security Guide for details.
All 2FA endpoints require the user to be authenticated via session cookie:
Cookie: session=your-session-idBase Path: /api/auth/2fa
Initiates the 2FA setup process for the authenticated user. This generates a new TOTP secret, QR code, and backup codes.
POST /api/auth/2fa/setupHeaders:
Cookie: session=your-session-id
Content-Type: application/jsonPermissions Required: Authenticated user only
Preconditions:
- User must be authenticated
- 2FA must NOT already be enabled for the user
Success (200):
{
"success": true,
"data": {
"secret": "JBSWY3DPEHPK3PXP",
"qrCodeURL": "otpauth://totp/SveltyCMS:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=SveltyCMS",
"manualEntryDetails": {
"issuer": "SveltyCMS",
"account": "user@example.com",
"secret": "JBSWY3DPEHPK3PXP",
"algorithm": "SHA1",
"digits": 6,
"period": 30
},
"backupCodes": ["A1B2C3D4", "E5F6G7H8", "I9J0K1L2", "M3N4O5P6", "Q7R8S9T0", "U1V2W3X4", "Y5Z6A7B8", "C9D0E1F2", "G3H4I5J6", "K7L8M9N0"]
},
"message": "2FA setup initiated. Please save your backup codes and scan the QR code with your authenticator app."
}Error Responses:
// 401 Unauthorized - User not authenticated
{
"message": "Authentication required"
}
// 400 Bad Request - 2FA already enabled
{
"message": "2FA is already enabled for this account"
}
// 500 Internal Server Error
{
"message": "Failed to initiate 2FA setup"
}- Save the secret and backup codes immediately - they cannot be retrieved again
- The QR code URL can be used to generate a QR code image for scanning
- Manual entry details are provided for authenticator apps that don't support QR codes
- The setup is NOT complete until the verification step succeeds
Completes the 2FA setup by verifying the first TOTP code from the user's authenticator app.
POST /api/auth/2fa/verify-setupHeaders:
Cookie: session=your-session-id
Content-Type: application/jsonBody:
{
"secret": "JBSWY3DPEHPK3PXP",
"verificationCode": "123456",
"backupCodes": ["A1B2C3D4", "E5F6G7H8", "I9J0K1L2", "M3N4O5P6", "Q7R8S9T0", "U1V2W3X4", "Y5Z6A7B8", "C9D0E1F2", "G3H4I5J6", "K7L8M9N0"]
}Permissions Required: Authenticated user only
Preconditions:
- User must be authenticated
- 2FA must NOT already be enabled
- Secret must match the one generated in setup
- Verification code must be valid
Success (200):
{
"success": true,
"message": "2FA has been successfully enabled for your account. Please save your backup codes in a secure location."
}Error Responses:
// 401 Unauthorized
{
"message": "Authentication required"
}
// 400 Bad Request - Invalid code
{
"message": "Invalid verification code. Please try again."
}
// 400 Bad Request - Already enabled
{
"message": "2FA is already enabled for this account"
}
// 500 Internal Server Error
{
"message": "Failed to complete 2FA setup"
}- Once verified, 2FA is immediately active
- The secret and backup codes are securely stored (hashed)
- The user will be required to provide a 2FA code on future logins
Verifies a 2FA code during authentication or for sensitive operations. Supports both TOTP codes and backup codes.
POST /api/auth/2fa/verifyHeaders:
Content-Type: application/jsonBody:
{
"userId": "user123",
"code": "123456"
}Permissions Required: None (used during authentication)
Success (200) - TOTP Code:
{
"success": true,
"message": "2FA verification successful",
"method": "totp",
"backupCodeUsed": false
}Success (200) - Backup Code:
{
"success": true,
"message": "2FA verification successful using backup code. 9 backup codes remaining.",
"method": "backup",
"backupCodeUsed": true
}Failed Verification (200):
{
"success": false,
"message": "Invalid 2FA code"
}Error Responses:
// 500 Internal Server Error
{
"message": "Failed to verify 2FA code"
}- This endpoint returns 200 even for failed verification (check
successfield) - Backup codes are single-use and removed after successful verification
- The
backupCodeUsedfield indicates if a backup code was consumed - TOTP codes are valid for 30 seconds (standard TOTP window)
Disables two-factor authentication for the authenticated user.
POST /api/auth/2fa/disableHeaders:
Cookie: session=your-session-id
Content-Type: application/jsonPermissions Required: Authenticated user only
Preconditions:
- User must be authenticated
- 2FA must be enabled
Success (200):
{
"success": true,
"message": "2FA has been disabled for your account."
}Error Responses:
// 401 Unauthorized
{
"message": "Authentication required"
}
// 400 Bad Request - 2FA not enabled
{
"message": "2FA is not enabled for this account"
}
// 500 Internal Server Error
{
"message": "Failed to disable 2FA"
}- All 2FA data (secret, backup codes) is removed
- User will no longer be prompted for 2FA codes
- This action should require additional verification (password confirmation) in production
Retrieves the current 2FA status for the authenticated user.
GET /api/auth/2fa/backup-codesHeaders:
Cookie: session=your-session-idPermissions Required: Authenticated user only
Success (200):
{
"success": true,
"data": {
"enabled": true,
"hasBackupCodes": true,
"backupCodesCount": 10,
"lastVerification": "2025-10-05T14:30:00Z"
}
}Error Responses:
// 401 Unauthorized
{
"message": "Authentication required"
}
// 500 Internal Server Error
{
"message": "Failed to get 2FA status"
}Generates a new set of backup codes, invalidating the old ones.
POST /api/auth/2fa/backup-codesHeaders:
Cookie: session=your-session-id
Content-Type: application/jsonPermissions Required: Authenticated user only
Preconditions:
- User must be authenticated
- 2FA must be enabled
Success (200):
{
"success": true,
"data": {
"backupCodes": ["A1B2C3D4", "E5F6G7H8", "I9J0K1L2", "M3N4O5P6", "Q7R8S9T0", "U1V2W3X4", "Y5Z6A7B8", "C9D0E1F2", "G3H4I5J6", "K7L8M9N0"]
},
"message": "New backup codes generated. Please save these codes in a secure location. Your old backup codes are no longer valid."
}Error Responses:
// 401 Unauthorized
{
"message": "Authentication required"
}
// 400 Bad Request - 2FA not enabled
{
"message": "2FA is not enabled for this account"
}
// 500 Internal Server Error
{
"message": "Failed to regenerate backup codes"
}- Old backup codes are immediately invalidated
- Store these codes securely - they are only shown once
- Each code can only be used once
- Users should regenerate codes if they suspect compromise
sequenceDiagram
participant User
participant Client
participant API
participant DB
User->>Client: Click "Enable 2FA"
Client->>API: POST /api/auth/2fa/setup
API->>API: Generate secret & backup codes
API-->>Client: Return secret, QR code, backup codes
Client->>User: Display QR code & backup codes
User->>User: Scan QR code with authenticator app
User->>User: Save backup codes securely
User->>Client: Enter 6-digit code from app
Client->>API: POST /api/auth/2fa/verify-setup
API->>API: Verify TOTP code
API->>DB: Store hashed secret & backup codes
API-->>Client: Success response
Client->>User: "2FA enabled successfully"
sequenceDiagram
participant User
participant Client
participant API
participant DB
User->>Client: Enter email & password
Client->>API: POST /api/auth/login
API->>DB: Verify credentials
API-->>Client: "2FA required" + userId
Client->>User: Show 2FA code input
User->>User: Open authenticator app
User->>Client: Enter 6-digit code
Client->>API: POST /api/auth/2fa/verify
API->>DB: Verify TOTP/backup code
API-->>Client: Success + session token
Client->>User: Redirect to dashboard
- Algorithm: SHA-1 (TOTP standard)
- Digits: 6
- Period: 30 seconds
- Time window: ±1 period (prevents timing issues)
- Format: 8 alphanumeric characters
- Storage: Quantum-resistant hashing using Argon2id (64 MB memory-hard)
- Single-use: Automatically removed after use
- Count: 10 codes per user
- Quantum security: Memory-hard hashing resists quantum speedup
- Always save backup codes - Store them in a password manager or secure location
- Verify setup immediately - Test the authenticator app before closing the setup dialog
- Regenerate if compromised - Use the regenerate endpoint if codes are exposed
- Monitor backup code usage - Track remaining codes via the status endpoint
- Secure the secret - Never expose the TOTP secret after setup
The 2FA data is stored in the User model:
interface User {
// ... other fields
is2FAEnabled?: boolean; // Whether 2FA is active
totpSecret?: string; // Encrypted TOTP secret
backupCodes?: string[]; // Hashed backup codes
last2FAVerification?: Date; // Last successful verification
}All endpoints follow consistent error patterns:
- 401: Authentication required
- 400: Bad request (precondition failed, invalid input)
- 500: Server error (database failure, crypto error)
Errors include descriptive messages for debugging.
Setup 2FA:
curl -X POST http://localhost:5173/api/auth/2fa/setup \
-H "Cookie: session=your-session-cookie" \
-H "Content-Type: application/json"Verify Setup:
curl -X POST http://localhost:5173/api/auth/2fa/verify-setup \
-H "Cookie: session=your-session-cookie" \
-H "Content-Type: application/json" \
-d '{
"secret": "YOUR_SECRET",
"verificationCode": "123456",
"backupCodes": ["A1B2C3D4", "E5F6G7H8", ...]
}'Verify 2FA Code:
curl -X POST http://localhost:5173/api/auth/2fa/verify \
-H "Content-Type: application/json" \
-d '{
"userId": "user123",
"code": "123456"
}'See tests/playwright/2fa.test.ts for comprehensive E2E tests.
For implementation details, see:
src/databases/auth/twoFactorAuth.ts- Service layersrc/databases/auth/totp.ts- TOTP and backup code utilitiessrc/routes/api/auth/2fa/- API endpoint implementations