patel / biometric-2fa-bundle
Symfony bundle for biometric 2FA using WebAuthn
Installs: 14
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/patel/biometric-2fa-bundle
Requires
- php: ^8.3
 - doctrine/dbal: ^4.2
 - lbuchs/webauthn: ^2.1
 - symfony/framework-bundle: ^6.3 || ^7.0
 
This package is auto-updated.
Last update: 2025-10-05 06:16:59 UTC
README
Symfony bundle for biometric 2FA using WebAuthn
patel/biometric-2fa-bundle is a Symfony bundle that enables biometric two-factor authentication (2FA) using WebAuthn with support for customizable user device storage, redirect paths, and logout integration.
🚀 Installation
composer require patel/biometric-2fa-bundle
Then enable the bundle in config/bundles.php (if not auto-loaded):
return [ Biometric2FA\Biometric2FABundle\Biometric2FABundle::class => ['all' => true], ];
⚙️ Configuration
Create a config file:
# config/packages/biometric_2fa.yaml biometric_2fa: rp_id: "localhost" rp_name: "Test App" device_entity: 'App\Entity\UserDevice' redirect_path: 'app_dashboard' logout_path: 'app_logout'
add this in doctrine.yaml
types: blob_string: Biometric2FA\Doctrine\DBAL\Types\BlobStringType
load bundle routes, (config/routes.yaml)
biometric_2fa: resource: '@Biometric2FABundle/Resources/config/routes.yaml'
add this in service.yaml, This line tells Symfony that whenever a service (like a controller or helper) needs the UserDeviceRepositoryInterface, it should use your actual UserDeviceRepository class.
Without it, Symfony cannot auto-wire the interface because interfaces can’t be instantiated, and you haven’t told Symfony which class to use.
Biometric2FA\Repository\UserDeviceRepositoryInterface: '@App\Repository\UserDeviceRepository'
🧩 Database Setup
Your app must implement a concrete UserDevice entity that extends the bundle's abstract class,
and map User entity with it, so we can store user devices.
use Biometric2FA\Entity\UserDevice as BaseDevice; class UserDevice extends BaseDevice { #[ORM\ManyToOne(targetEntity: User::class)] #[ORM\JoinColumn(nullable: false)] private BiometricUserInterface $user; public function getUser(): BiometricUserInterface { return $this->user; } public function setUser(BiometricUserInterface $user): static { $this->user = $user; return $this; } }
And a repository class that implements:
use Biometric2FA\Repository\UserDeviceRepositoryInterface; class UserDeviceRepository extends ServiceEntityRepository implements UserDeviceRepositoryInterface { public function getCredentialsForUser(UserInterface $user): array { return $this->createQueryBuilder('d') ->select('d.credentialId') ->where('d.user = :user') ->setParameter('user', $user) ->getQuery() ->getSingleColumnResult(); } }
🧠 User Interface Requirements
Your User entity should implement:
use Biometric2FA\Security\BiometricUserInterface; class User implements BiometricUserInterface { private bool $enableBioMetricsFor2fa = false; public function isBiometric2FAEnabled(): bool { return $this->enableBioMetricsFor2fa; } public function setBiometric2FAEnabled(bool $enabled): void { $this->enableBioMetricsFor2fa = $enabled; } }
🛡️ Routes
The bundle exposes the following biometric routes (protected):
| Route Name | Path | Purpose | 
|---|---|---|
app_biometric_auth | 
/biometric/auth | 
Biometric login UI | 
bio_metrics_get_args | 
/biometric/get-args | 
Generate WebAuthn challenge args | 
bio_metrics_create_args | 
/biometric/create-args | 
Setup credentials challenge args | 
bio_metrics_process_create | 
/biometric/process-create | 
Save credential | 
bio_metrics_verify | 
/biometric/verify | 
Verify login assertion | 
bio_metrics_bio_metrics_settings | 
/biometric/settings | 
For enable/disable biometric | 
✨ Usage in Twig
Biometric Settings UI:
<a href="{{ path(logout_path) }}">Logout</a>
📦 Features
- WebAuthn support for biometric authentication
 - Device registration and secure verification
 - Customizable redirect/logout path via config
 - Event subscriber to enforce biometric check post-login
 
🧪 Testing
Ensure you call:
php bin/console doctrine:schema:update --force
Register your fingerprint and enable biometric login from the settings page.
📄 License
This bundle is released under the MIT License.
🔐 Biometric Authentication Flow
This screen prompts the user to authenticate using a biometric method such as fingerprint or Face ID.
It appears automatically when biometric 2FA is required after login.
⚙️ Settings Page
This page allows users to enable or disable biometric authentication for their account.
Changes are saved securely and reflected immediately in the login flow.
✨ Template Override Guide
You can fully override the default templates provided by the bundle while keeping the JavaScript functionality working.
✅ Required Steps
- Include the JS files in your custom layout:
 
<script src="{{ path('common_biometrics_js') }}"></script> <script src="{{ path('register_biometrics_js') }}"></script> <script src="{{ path('verify_biometrics_js') }}"></script>
- Use the following 
data-*attributes in your HTML to ensure JavaScript works correctly: 
| Purpose | Required Attribute | 
|---|---|
| Biometric Auth Button | data-biometric-auth | 
| Settings Form | data-biometric-settings-form | 
✅ Example Override for Authentication Page
{% extends '@Biometric2FA/layout.html.twig' %}
{% block biometric_auth_content %}
    <button data-biometric-auth class="btn">Authenticate</button>
{% endblock %}
✅ Example Override for Settings Page
{% extends '@Biometric2FA/layout.html.twig' %}
{% block biometric_auth_content %}
    <form data-biometric-settings-form>
        ...
    </form>
{% endblock %}
✅ Flash Message Rendering (included in layout)
The layout automatically renders flash messages on page reload using Symfony's FlashBag.