PHPackages                             restruct/silverstripe-mfa-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. restruct/silverstripe-mfa-bundle

ActiveSilverstripe-vendormodule[Authentication &amp; Authorization](/categories/authentication)

restruct/silverstripe-mfa-bundle
================================

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

1.3.4(3mo ago)0163↓50%MITPHP

Since Feb 3Pushed 3mo agoCompare

[ Source](https://github.com/restruct/silverstripe-mfa-bundle)[ Packagist](https://packagist.org/packages/restruct/silverstripe-mfa-bundle)[ RSS](/packages/restruct-silverstripe-mfa-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (4)Versions (14)Used By (0)

Silverstripe MFA Bundle
=======================

[](#silverstripe-mfa-bundle)

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

Quick Start
-----------

[](#quick-start)

1. `composer require restruct/silverstripe-mfa-bundle`
2. Add `SS_MFA_SECRET_KEY` to `.env`, run `dev/build`

That's it. MFA is enforced with a 6-month grace period out of the box.

Features
--------

[](#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
------------

[](#requirements)

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

Installation
------------

[](#installation)

```
composer require restruct/silverstripe-mfa-bundle
```

Configuration
-------------

[](#configuration)

### 1. Set encryption key (required)

[](#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)

[](#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)

[](#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. MFA requirement (enabled by default)

[](#4-mfa-requirement-enabled-by-default)

This bundle automatically enables "MFA Required" on first `dev/build` and hides the SiteConfig MFA settings. Users will be prompted to set up MFA on their next login.

A **grace period of 6 months** is set by default, allowing users to skip MFA setup temporarily. After the grace period expires, MFA becomes mandatory.

```
# Customize grace period (default: 180 days = 6 months)
Restruct\MFABundle\Extensions\SiteConfigMFAExtension:
  grace_period_days: 90   # 3 months
  # grace_period_days: 0  # No grace period - MFA required immediately
```

To show the MFA settings in SiteConfig (for manual control):

```
Restruct\MFABundle\Extensions\SiteConfigMFAExtension:
  show_mfa_settings: true
```

### 5. Disable during development (optional)

[](#5-disable-during-development-optional)

Add to `.env`:

```
BYPASS_MFA=1
```

Configuration Reference
-----------------------

[](#configuration-reference)

### Bundle settings

[](#bundle-settings)

ClassSettingDefaultDescription`SiteConfigMFAExtension``grace_period_days`180Days users can skip MFA (0 = no grace period)`SiteConfigMFAExtension``show_mfa_settings`falseShow MFA fields in SiteConfig`TOTPConfigExtension``issuer`SiteConfig TitleApp name shown in authenticator`TOTPConfigExtension``period`30Seconds per code`TOTPConfigExtension``algorithm`sha1Hash algorithm (sha1/sha256/sha512)### SilverStripe TOTP settings (set directly on SS classes)

[](#silverstripe-totp-settings-set-directly-on-ss-classes)

SettingClassDefaultDescription`code_length``Method`6Number of digits (6-8)`secret_length``RegisterHandler`16Secret key length### SilverStripe WebAuthn settings (set directly on SS classes)

[](#silverstripe-webauthn-settings-set-directly-on-ss-classes)

SettingClassDefaultDescription`authenticator_attachment``RegisterHandler``null`\*Allowed authenticator types\*This bundle sets the default to `null` (allow both). SilverStripe's default is `cross-platform` (security keys only).

### Help link settings (set by this bundle)

[](#help-link-settings-set-by-this-bundle)

ClassSettingDefault`SilverStripe\TOTP\RegisterHandler``user_help_link``/mfa-help/totp``SilverStripe\WebAuthn\RegisterHandler``user_help_link``/mfa-help/webauthn``SilverStripe\MFA\Authenticator\LoginHandler``user_help_link``/mfa-help/``SilverStripe\MFA\BackupCode\RegisterHandler``user_help_link``/mfa-help/backup-codes`Override these if you use a custom URL segment or external help pages.

**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

[](#mfa-enforcement)

SettingClassDefaultDescription`required_mfa_methods``EnforcementManager`1Minimum methods requiredHow it works
------------

[](#how-it-works)

### TOTP (Authenticator App)

[](#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)

[](#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
----------------

[](#admin-management)

### Resetting user MFA

[](#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

[](#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
---------------

[](#troubleshooting)

### "This method has not been configured yet"

[](#this-method-has-not-been-configured-yet)

The `SS_MFA_SECRET_KEY` environment variable is not set.

### WebAuthn "Security key" option not showing

[](#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

[](#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

[](#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
------------------------------------------

[](#understanding-webauthn-authenticator-types)

WebAuthn supports different authenticator types with different trade-offs:

### Platform vs Cross-Platform

[](#platform-vs-cross-platform)

TypeExamplesProsCons**Platform**Touch ID, Face ID, Windows HelloFree, built-in, convenientTied to single device**Cross-platform**YubiKey, USB/NFC security keysPortable, works anywhereRequires purchasing hardware### Passkeys (Synced Credentials)

[](#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

[](#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
----------

[](#help-pages)

This bundle includes translatable help pages served at `/mfa-help/`:

URLContent`/mfa-help/`Overview of MFA`/mfa-help/totp`Authenticator app setup`/mfa-help/webauthn`Security key / biometrics setup`/mfa-help/backup-codes`Backup codes explanationHelp pages automatically display in the logged-in user's CMS locale (from `Member.Locale`), falling back to the site's default locale. Translations are included for: English, Dutch, German, French, and Spanish.

### Disabling Help Pages

[](#disabling-help-pages)

To disable the built-in help pages entirely, set `DISABLE_MFA_HELP` as an environment variable or PHP constant:

```
# .env
DISABLE_MFA_HELP=1
```

Or in `app/_config.php`:

```
define('DISABLE_MFA_HELP', true);
```

### Changing the URL Segment

[](#changing-the-url-segment)

To serve help pages at a different URL (e.g., `/hulp/`):

1. Disable the default route via `DISABLE_MFA_HELP`
2. Configure your custom URL segment and Director rule:

```
# app/_config/mfa-help.yml
Restruct\MFABundle\Controllers\MFAHelpController:
  url_segment: 'hulp'

SilverStripe\Control\Director:
  rules:
    'hulp': 'Restruct\MFABundle\Controllers\MFAHelpController'
```

3. Update the help URLs to match your custom segment:

```
SilverStripe\TOTP\RegisterHandler:
  user_help_link: '/hulp/totp'

SilverStripe\WebAuthn\RegisterHandler:
  user_help_link: '/hulp/webauthn'

SilverStripe\MFA\Authenticator\LoginHandler:
  user_help_link: '/hulp/'

SilverStripe\MFA\BackupCode\RegisterHandler:
  user_help_link: '/hulp/backup-codes'
```

### Customizing Help Content

[](#customizing-help-content)

Override the translations via lang files in your project, 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
---------------

[](#further-reading)

### SilverStripe Documentation

[](#silverstripe-documentation)

- [MFA Module](https://github.com/silverstripe/silverstripe-mfa) - Core MFA framework
- [TOTP Authenticator](https://github.com/silverstripe/silverstripe-totp-authenticator/blob/6/docs/en/index.md) - Authenticator app configuration
- [WebAuthn Authenticator](https://github.com/silverstripe/silverstripe-webauthn-authenticator/blob/master/docs/en/readme.md) - Security keys configuration

### WebAuthn Specifications

[](#webauthn-specifications)

- [WebAuthn Guide](https://webauthn.guide/) - Introduction to WebAuthn
- [Authenticator Selection Criteria](https://github.com/web-auth/webauthn-framework/blob/1.2.x/doc/webauthn/PublicKeyCredentialCreation.md#authenticator-selection-criteria) - Technical details on authenticator filtering

License
-------

[](#license)

MIT

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance80

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

13

Last Release

103d ago

Major Versions

0.3.0 → 1.0.02026-02-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/4d3680d6353e5f171543435b89965ba2588186ad7ec0ec97cbf572704fec2a4f?d=identicon)[micschk](/maintainers/micschk)

---

Top Contributors

[![micschk](https://avatars.githubusercontent.com/u/1005986?v=4)](https://github.com/micschk "micschk (20 commits)")

---

Tags

totpAuthenticationsilverstripe2fawebauthnMFA

### Embed Badge

![Health badge](/badges/restruct-silverstripe-mfa-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/restruct-silverstripe-mfa-bundle/health.svg)](https://phpackages.com/packages/restruct-silverstripe-mfa-bundle)
```

###  Alternatives

[chillerlan/php-authenticator

A generator for counter- and time based 2-factor authentication codes (Google Authenticator). PHP 8.2+

58119.1k2](/packages/chillerlan-php-authenticator)[kelunik/two-factor

Two factor authentication.

371.9k1](/packages/kelunik-two-factor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
