PHPackages                             jbtronics/2fa-webauthn - 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. jbtronics/2fa-webauthn

ActiveSymfony-bundle[Authentication &amp; Authorization](/categories/authentication)

jbtronics/2fa-webauthn
======================

Webauthn Two-Factor-Authentication Plugin for scheb/2fa

v3.0.0(10mo ago)1559.6k↑107.7%4[1 PRs](https://github.com/jbtronics/2fa-webauthn/pulls)MITPHPPHP ^8.2

Since Oct 3Pushed 10mo ago2 watchersCompare

[ Source](https://github.com/jbtronics/2fa-webauthn)[ Packagist](https://packagist.org/packages/jbtronics/2fa-webauthn)[ RSS](/packages/jbtronics-2fa-webauthn/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (9)Dependencies (9)Versions (10)Used By (0)

Webauthn Two-Factor-Authentication Plugin for scheb/2fa
=======================================================

[](#webauthn-two-factor-authentication-plugin-for-scheb2fa)

This repository contains a plugin for [scheb/2fa](https://github.com/scheb/2fa) that adds support for Webauthn authenticators (like a Yubikey) as a second factor.

Features
--------

[](#features)

- Support of all webauthn authenticators as second factor
- Supports multiple authenticators per user
- Backward compatibility for existing registered U2F keys (from [r/u2f-two-factor-bundle](https://github.com/darookee/u2f-two-factor-bundle))

Requirements
------------

[](#requirements)

- Symfony 7
- PHP 8.2 or later
- webauthn/webauthn-lib 5.0 or later

If you want to use symfony 5.\* and PHP 7.4, use the version 1.0.0 of this bundle. If you want to use PHP 8.1 and webauthn/webauthn-lib 4.\*, use the version 2.0.0 of this bundle.

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

[](#installation)

1. Install the bundle `composer require jbtronics/2fa-webauthn`
2. Enable the bundle in your `config/bundles.php` (normally done by Symfony flex automatically)
3. If you want to use the easy doctrine integration, add the web-authn symfony bundle: `composer require web-auth/webauthn-symfony-bundle`. You do not need to run the community recipe, as we just use the doctrine type definitons from the bundle. Add `Webauthn\Bundle\WebauthnBundle::class => ['all' => true],` to your `config/bundles.php` instead.

Setup and Usage
---------------

[](#setup-and-usage)

After following the Installation steps, do the follwing steps to setup the library:

1. Add `Jbtronics\TFAWebauthn\Model\TwoFactorInterface` interface to your user entity:

```
use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface;

class User implements WebauthnTwoFactorInterface
{
    /**
     * @var Collection
     * @ORM\OneToMany(targetEntity="App\Entity\WebauthnKey", mappedBy="user", cascade={"REMOVE"}, orphanRemoval=true)
     */
    private $webauthnKeys;

    /**
     * Determines whether the user has 2FA using Webauthn enabled
     * @return bool True if the webauthn 2FA is enabled, false otherwise
     */
    public function isWebAuthnAuthenticatorEnabled(): bool
    {
        //Return true to enable webauthn 2FA
        return count($this->webauthnKeys) > 0;
    }

    /**
     * Returns a list of all legacy U2F keys, associated with this user
     * Return an empty array, if this user does not have any legacy U2F keys.
     * @return iterable
     */
    public function getLegacyU2FKeys(): iterable
    {
        return []; //If you have no legacy U2F keys, return just an empty array
        //return $this->u2f_keys; //Otherwise return the legacy keys (see migration section below)
    }

    /**
     * Returns a list of all webauthn keys, associated with this user
     * @return iterable
     */
    public function getWebauthnKeys(): iterable
    {
        return $this->webauthnKeys;
    }

    /**
     * Returns the webauthn user entity that should be used for this user.
     * @return PublicKeyCredentialUserEntity
     */
    public function getWebAuthnUser(): PublicKeyCredentialUserEntity
    {
        //Return webauthn user definition for this user. As we just use it as an two-factor authentication, the values here are most likely not that important
        return new PublicKeyCredentialUserEntity(
            $this->getUsername(), // The Webauthn Name (like a username)
            $this->getID(), // A unique identifier for this user
            $this->getDisplayName() // The display name of this user (optional, otherwise null)
        );
    }
}
```

2. Create a new entity for the webauthn keys. For simplicity we use the templates from the web-auth/webauthn-symfony-bundle (see [here](https://webauthn-doc.spomky-labs.com/v/v3.3/the-webauthn-server/the-symfony-way/entities-with-doctrine) for more infos)

```
declare(strict_types=1);

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource;

#[ORM\Entity]
#[ORM\Table(name: 'webauthn_keys')]
class WebAuthnKey extends BasePublicKeyCredentialSource
{
    #[ORM\Id]
    #[ORM\Column(type: Types::INTEGER)]
    #[ORM\GeneratedValue]
    private $id;

    #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'webauthn_keys')]
    protected ?User $user = null;

    //You can declare additional fields too, if you want to store additional information about the key (like a name)
    private $name;

    public function getId(): string
    {
        return $this->id;
    }

    public static function fromRegistration(BasePublicKeyCredentialSource $registration): self
    {
        return new self(
            publicKeyCredentialId:  $registration->publicKeyCredentialId,
            type:  $registration->type,
            transports: $registration->transports,
            attestationType:  $registration->attestationType,
            trustPath:  $registration->trustPath,
            aaguid:  $registration->aaguid,
            credentialPublicKey:  $registration->credentialPublicKey,
            userHandle:  $registration->userHandle,
            counter:  $registration->counter,
            otherUI:  $registration->otherUI,
            backupEligible:  $registration->backupEligible,
            backupStatus:  $registration->backupStatus,
            uvInitialized:  $registration->uvInitialized,
        );
    }
}
```

3. Include javascript frontend code into your project: For webauthn we need some javascript code to interact with the authenticators. Copy the file from `assets/tfa_webauthn.js` to your project and include it either by loading it via a `` tag or by including it in your webpack using `.addEntry()`.
4. Add configuration file `config/packages/jbtronics_2fa_webauthn.yaml`:

```
tfa_webauthn:
  enabled: true

  # Optional configuration options:

  # timeout: 60000 # The timeout in millisceconds to allow the user to interact with the authenticator. Default: 60000
  # template: '' # The template to use for the login form

  # rpID: null # The relying party ID of your application. If null, the current host will be used. Default: null
  # U2FAppID: null # The U2F AppID of your application. If null, the current host will be used. Default: null

  # These settings are most likely not important for two-factor authentication:
  # rpName: 'My Application' # The relying party name of your application, Default: 'My Application'
  # rpIcon: null # The relying party icon of your application. Default: null
```

5. Customize the login template: Similar to the base login template of the `scheb/2fa` bundle you will most likely need to override the login template of this bundle to integrate it into your design. Copy the template from `Resources/views/Authentication/form.html.twig` to your project and customize it to your needs. Configure the `template` setting in the bundle config to your new path.

Registration of new keys
------------------------

[](#registration-of-new-keys)

In principle the login with exsting keys should work now, but you will most likely need some possibility to register new keys. To make this easy there is the `Jbtronics\TFAWebauthn\Services\TFAWebauthnRegistrationHelper` service to help you with this:

1. Create a new controller, which will handle the registration, which should looks like this:

```
    use Jbtronics\TFAWebauthn\Services\TFAWebauthnRegistrationHelper;Ä

    class WebauthnKeyRegistrationController extends AbstractController
{
    /**
     * @Route("/webauthn/register", name="webauthn_register")
     */
    public function register(Request $request, TFAWebauthnRegistrationHelper $registrationHelper, EntityManagerInterface $em)
    {

        //If form was submitted, check the auth response
        if ($request->getMethod() === 'POST') {
            $webauthnResponse = $request->request->get('_auth_code');

            //Retrieve other data from the form, that you want to store with the key
            $keyName = $request->request->get('keyName');

            try {
                //Check the response
                $new_key = $registrationHelper->checkRegistrationResponse($webauthnResponse);
            } catch (Exception $exception) {
                // Handle errors...
            }

            //If we got here, the registration was successful. Now we can store the new key in the database

            //Convert our returned key into an database entity and persist it...
            $keyEntity = WebauthnKey::fromRegistration($new_key);
            $keyEntity->setName($keyName);
            $keyEntity->setUser($this->getUser());

            $em->persist($keyEntity);
            $em->flush();

            $this->addFlash('success', 'Key registered successfully');
            //We are finished here so return to another page
            return $this->redirectToRoute('homepage');
        }

        return $this->render(
            'webauthn_register.html.twig',
            [
                //Generate the registration request
                'registrationRequest' => $registrationHelper->generateRegistrationRequestAsJSON(),
            ]
        );
    }
}
```

2. Create a template with a form, which will be used to register the new key. The form should look like this:

```

    Add new Key

```

The `data-webauthn-tfa-action` attribute marks the form as webauthn registration form and is handled by the frontend code included above. If the form is submitted, the frontend code will catch that and start a registration process. The response is put it into the hidden input field with the id `_auth_code` and sent to our controller for parsing.

Migrate from r/u2f-two-factor-bundle
------------------------------------

[](#migrate-from-ru2f-two-factor-bundle)

1. Replace the `R\U2FTwoFactorBundle\Model\U2F\TwoFactorKeyInterface` interface of your U2FKey entity with `Jbtronics\TFAWebauthn\Model\LegacyU2FKeyInterface` and remove the fromRegistrationData() function (as we do not need it anymore).
2. Replace the `R\U2FTwoFactorBundle\Model\U2F\TwoFactorInterface` interface of your user with `Jbtronics\TFAWebauthn\Model\TwoFactorInterface`, configure it (see above) and replace/rename your `getU2FKeys()` function to `getLegacyU2FKeys()`.
3. (Optional:) If your appID is not the same as your domain, configure it with the `U2FAppID` option. But this should normally not be needed
4. Remove the old routes, templates and settings of the `r/u2f-two-factor-bundle` and remove it from your application
5. Follow the setup steps above

License
-------

[](#license)

This bundle is licensed under the MIT license. See [LICENSE](LICENSE) for details.

Credits
-------

[](#credits)

- Webauthn support is provided by [spomky-labs webauthn-framework](https://github.com/web-auth/webauthn-framework)
- This library is inspired by the [r/u2f-two-factor-bundle](r/u2f-two-factor-bundle) bundle

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance53

Moderate activity, may be stable

Popularity41

Moderate usage in the ecosystem

Community12

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 98.3% 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 ~130 days

Recently: every ~154 days

Total

9

Last Release

323d ago

Major Versions

v1.0.0 → v2.0.02023-06-11

v2.2.3 → v3.0.02025-08-14

PHP version history (3 changes)v1.0.0PHP ^7.4.0|^8.0

v2.0.0PHP ^8.1

v3.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/966f0c4a6fd593c7a9e3e0c950f4e44dfa6caaf09609500cdce765b1eba7a855?d=identicon)[jbtronics](/maintainers/jbtronics)

---

Top Contributors

[![jbtronics](https://avatars.githubusercontent.com/u/5410681?v=4)](https://github.com/jbtronics "jbtronics (57 commits)")[![ownede](https://avatars.githubusercontent.com/u/442603?v=4)](https://github.com/ownede "ownede (1 commits)")

---

Tags

2fasymfonysymfony-bundletwo-factortwo-factor-authenticationwebauthnsymfony2faTwo Factor AuthenticationwebauthnSymfony Bundlescheb-2fa

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jbtronics-2fa-webauthn/health.svg)

```
[![Health](https://phpackages.com/badges/jbtronics-2fa-webauthn/health.svg)](https://phpackages.com/packages/jbtronics-2fa-webauthn)
```

###  Alternatives

[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

515100.5k3](/packages/web-auth-webauthn-framework)[contao/core-bundle

Contao Open Source CMS

1231.6M2.8k](/packages/contao-core-bundle)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M203](/packages/sulu-sulu)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M574](/packages/shopware-core)[rcsofttech/audit-trail-bundle

Enterprise-grade, high-performance Symfony audit trail bundle. Automatically track Doctrine entity changes with split-phase architecture, multiple transports (HTTP, Queue, Doctrine), and sensitive data masking.

1189.8k](/packages/rcsofttech-audit-trail-bundle)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)

PHPackages © 2026

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