---
name: contentbox-cfml-two-factor-authentication
description: "Use this skill when implementing or customizing ContentBox two-factor authentication providers, trusted device flows, enrollment/verification UX, enforcement policies, and provider lifecycle handling."
applyTo: "**/*.{cfc,cfm,cfml}"
---
# ContentBox Two-Factor Authentication (CFML)
Implement and extend two-factor authentication (2FA) in ContentBox CMS using CFML. ContentBox provides a pluggable 2FA system with provider interfaces, trusted device support, and global enforcement.
## 2FA Architecture
The 2FA system lives at `modules/contentbox/models/security/twofactor/`:
| Component | File | Purpose |
|-----------|------|---------|
| **Interface** | `ITwoFactorProvider.cfc` | Contract all 2FA providers must implement |
| **Base Class** | `BaseTwoFactorProvider.cfc` | Base class with injected services |
| **Service** | `TwoFactorService.cfc` | Provider registry and orchestration |
### TwoFactorService
The central service manages 2FA providers and settings:
```cfml
property name="twoFactorService" inject="twoFactorService@contentbox";
// Provider management
twoFactorService.registerProvider( provider )
twoFactorService.unRegisterProvider( name )
twoFactorService.getRegisteredProviders()
twoFactorService.getRegisteredProvidersWithDisplayNames()
twoFactorService.getProvider( name )
// Settings
twoFactorService.isForceTwoFactorAuth()
twoFactorService.getDefaultProvider()
twoFactorService.getDefaultProviderObject()
twoFactorService.getTrustedDeviceTimespan()
```
### 2FA Settings
Stored in the `cb_setting` table:
| Setting Key | Description |
|-------------|-------------|
| `cb_security_2factorAuth_force` | Force global 2FA enrollment (true/false) |
| `cb_security_2factorAuth_provider` | Default provider name |
| `cb_security_2factorAuth_trusted_days` | Trusted device cookie duration (days) |
### Trusted Device Cookie
```cfml
variables.TRUSTED_DEVICE_COOKIE = "contentbox_2factor_device"
```
When `allowTrustedDevice()` returns `true`, a cookie is set. If the user logs in from the same device within the trusted timespan, 2FA validation is skipped.
## ITwoFactorProvider Interface
All 2FA providers must implement this interface:
```cfml
interface {
/**
* Get the internal name of a provider, used for registration, internal naming and more.
*/
function getName();
/**
* Get the display name for the provider. Used in all UI screens.
*/
function getDisplayName();
/**
* Returns HTML to display to the user for required two-factor fields.
*/
function getAuthorSetupForm( required author );
/**
* Get the display help for the provider. Used in the UI setup screens for the author.
*/
function getAuthorSetupHelp( required author );
/**
* Get the verification help for the provider. Used in the UI verification screen.
*/
function getVerificationHelp();
/**
* If true, ContentBox will set a tracking cookie for the user's browser.
* If the user logs in and the device is within the trusted timespan,
* no two-factor authentication validation will occur.
*/
boolean function allowTrustedDevice();
/**
* Send a challenge via the 2 factor auth implementation.
*
* @author The author to challenge
* @return struct:{ error:boolean, messages=string }
*/
struct function sendChallenge( required author );
/**
* Verify a challenge for the specific user.
*
* @code The verification code
* @author The author to verify challenge
* @return struct:{ error:boolean, messages:string }
*/
struct function verifyChallenge( required string code, required author );
/**
* Called once a two factor challenge is accepted and valid.
* The user has completed validation and will be logged in.
*
* @code The verification code
* @author The author to verify challenge
*/
function finalize( required string code, required author );
}
```
## Creating a Custom 2FA Provider
### Base Provider
Extend `BaseTwoFactorProvider` for auto-injected services:
```cfml