restruct/silverstripe-mfa-bundle

Portable Silverstripe MFA bundle with TOTP and WebAuthn support, plus configurable TOTP settings

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

Type:silverstripe-vendormodule

pkg:composer/restruct/silverstripe-mfa-bundle

0.3.0 2026-02-03 16:00 UTC

This package is auto-updated.

Last update: 2026-02-03 17:37:06 UTC


README

Portable MFA bundle for Silverstripe 5 with TOTP (Google Authenticator) and WebAuthn (security keys/biometrics) support.

Features

  • Bundles silverstripe/mfa, silverstripe/totp-authenticator, and silverstripe/webauthn-authenticator
  • Configurable TOTP settings (issuer name, period, algorithm)
  • WebAuthn configured to allow both biometrics (Touch ID) and security keys
  • Admin interface to reset/remove user MFA methods
  • Sensible defaults: requires at least 1 MFA method

Requirements

  • Silverstripe ^5.0
  • PHP ^8.1
  • ext-bcmath PHP extension (required by WebAuthn)

Installation

composer require restruct/silverstripe-mfa-bundle

Configuration

1. Set encryption key (required)

Add to your .env:

SS_MFA_SECRET_KEY="your-secure-random-key-here"

Generate a key:

php -r "echo bin2hex(random_bytes(32));"

2. Configure TOTP settings (optional)

Create app/_config/mfa.yml:

# Settings via this bundle's extension
Restruct\MFABundle\Extensions\TOTPConfigExtension:
  issuer: 'My Company CMS'      # Name shown in authenticator apps
  period: 30                     # Seconds per code (default: 30)
  algorithm: 'sha1'              # sha1, sha256, sha512 (default: sha1)

# Settings on SilverStripe's TOTP classes (set directly)
SilverStripe\TOTP\Method:
  code_length: 6                 # Number of digits (default: 6)

SilverStripe\TOTP\RegisterHandler:
  secret_length: 16              # Length of generated secret (default: 16)
  user_help_link: 'https://example.com/mfa-help'  # Help link during setup

3. Configure WebAuthn settings (optional)

By default, this bundle allows both platform authenticators (Touch ID, Windows Hello, Face ID) and cross-platform authenticators (USB security keys). You can restrict this:

SilverStripe\WebAuthn\RegisterHandler:
  # null = both types (default set by this bundle)
  # 'platform' = biometrics only (Touch ID, Windows Hello)
  # 'cross-platform' = security keys only (SilverStripe default)
  authenticator_attachment: ~

  # Custom help link shown during setup
  user_help_link: 'https://example.com/webauthn-help'

Note: WebAuthn requires HTTPS and a supported browser (Chrome, Firefox, Safari, Edge).

4. Enable MFA requirement (optional)

In the CMS: Settings → Access → MFA Required

Or via config:

SilverStripe\MFA\Service\EnforcementManager:
  required_mfa_methods: 1

5. Disable during development (optional)

Add to .env:

BYPASS_MFA=1

Configuration Reference

Bundle extension settings

Setting Default Description
issuer SiteConfig Title App name shown in authenticator
period 30 Seconds per code
algorithm sha1 Hash algorithm (sha1/sha256/sha512)

SilverStripe TOTP settings (set directly on SS classes)

Setting Class Default Description
code_length Method 6 Number of digits (6-8)
secret_length RegisterHandler 16 Secret key length
user_help_link RegisterHandler SS docs Help link during setup

SilverStripe WebAuthn settings (set directly on SS classes)

Setting Class Default Description
authenticator_attachment RegisterHandler null* Allowed authenticator types
user_help_link RegisterHandler SS docs Help link during setup

*This bundle sets the default to null (allow both). SilverStripe's default is cross-platform (security keys only).

Authenticator attachment options:

  • ~ or null: Both platform and cross-platform (recommended)
  • 'platform': Only biometrics (Touch ID, Windows Hello, Face ID)
  • 'cross-platform': Only USB/NFC security keys

MFA enforcement

Setting Class Default Description
required_mfa_methods EnforcementManager 1 Minimum methods required

How it works

TOTP (Authenticator App)

  1. A secret is generated and encrypted with SS_MFA_SECRET_KEY
  2. The QR code shows your configured issuer name
  3. User scans with Google Authenticator, Authy, 1Password, etc.
  4. On login, user enters the 6-digit code from their app

WebAuthn (Security Key / Biometrics)

  1. User registers their authenticator (USB key, Touch ID, etc.)
  2. A credential is stored, tied to your domain
  3. On login, user taps their key or uses biometrics

Note: WebAuthn credentials are domain-specific. Not recommended with silverstripe/subsites as each subsite domain would need separate credentials.

Admin Management

Resetting user MFA

Admins with the MFA_ADMINISTER_REGISTERED_METHODS permission can manage MFA for other users:

  1. Go to Security → Users and edit a user
  2. Find the Registered MFA Methods GridField (only shown for users with MFA configured)
  3. Delete any MFA methods to force the user to re-register

When all MFA methods are removed, the user will be prompted to set up MFA again on their next login.

Note: This GridField only appears when viewing other users' accounts, not your own (use the standard MFA interface for self-management).

Alternative: Account Reset Email

SilverStripe MFA also includes a built-in "Send account reset email" button that sends the user a link to reset both their password and MFA settings. This is useful when you want the user to verify their identity via email.

Troubleshooting

"This method has not been configured yet"

The SS_MFA_SECRET_KEY environment variable is not set.

WebAuthn "Security key" option not showing

  • Ensure you're using HTTPS (required by WebAuthn)
  • Check browser support (Chrome, Firefox, Safari, Edge)
  • Verify authenticator_attachment isn't set to 'cross-platform' if you want biometrics

WebAuthn not working with Touch ID / Windows Hello

The default SilverStripe setting only allows USB security keys. This bundle changes it to allow both, but if you've overridden authenticator_attachment, ensure it's set to ~ (null) or 'platform'.

Testing locally

Use BYPASS_MFA=1 in .env to skip MFA during development.

Note: WebAuthn passkeys require a trusted HTTPS certificate. Self-signed certificates may cause registration to fail with Chrome's native passkey storage.

Understanding WebAuthn Authenticator Types

WebAuthn supports different authenticator types with different trade-offs:

Platform vs Cross-Platform

Type Examples Pros Cons
Platform Touch ID, Face ID, Windows Hello Free, built-in, convenient Tied to single device
Cross-platform YubiKey, USB/NFC security keys Portable, works anywhere Requires purchasing hardware

Passkeys (Synced Credentials)

Modern browsers support passkeys - WebAuthn credentials that sync across devices:

  • iCloud Keychain: Syncs across Apple devices (Mac, iPhone, iPad)
  • Google Password Manager: Syncs across Chrome browsers logged into same Google account
  • Password managers: 1Password, Bitwarden, Proton Pass can store passkeys

When a user registers WebAuthn with authenticator_attachment: ~ (both), the browser offers choices:

  1. This device (platform) - Touch ID/Face ID, may sync via iCloud/Google
  2. Security key (cross-platform) - USB/NFC hardware key
  3. Phone/tablet - Use another device via QR code

Users can register multiple authenticators for redundancy.

Recommendation

This bundle defaults to authenticator_attachment: ~ (allow both) for maximum flexibility. Users can choose based on their needs:

  • Office workers with one machine → Touch ID
  • Mobile workers → Synced passkey or hardware key
  • High-security environments → Hardware keys only ('cross-platform')

Help Pages

This bundle includes Dutch help pages served locally at /mfa-help/:

URL Content
/mfa-help/ Overview of MFA
/mfa-help/totp Authenticator app setup
/mfa-help/webauthn Security key / biometrics setup
/mfa-help/backup-codes Backup codes explanation

Customizing Help Content

Override the content via config:

Restruct\MFABundle\Controllers\MFAHelpController:
  help_content:
    totp:
      title: 'Custom Title'
      content: '<p>Your custom HTML content...</p>'

Or point to your own URLs:

SilverStripe\TOTP\RegisterHandler:
  user_help_link: 'https://your-site.com/help/totp'

SilverStripe\WebAuthn\RegisterHandler:
  user_help_link: 'https://your-site.com/help/security-keys'

SilverStripe\MFA\Authenticator\LoginHandler:
  user_help_link: 'https://your-site.com/help/mfa'

SilverStripe\MFA\BackupCode\RegisterHandler:
  user_help_link: 'https://your-site.com/help/backup-codes'

To disable help links entirely, set them to empty strings.

Further Reading

SilverStripe Documentation

WebAuthn Specifications

License

MIT