PHPackages                             muyaedward/laravel-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. [Security](/categories/security)
4. /
5. muyaedward/laravel-webauthn

ActiveLibrary[Security](/categories/security)

muyaedward/laravel-webauthn
===========================

Laravel Webauthn support

4.6.0(1y ago)04.4kMITPHPPHP &gt;=8.1

Since Oct 20Pushed 1y agoCompare

[ Source](https://github.com/muyaedward/laravel-webauthn)[ Packagist](https://packagist.org/packages/muyaedward/laravel-webauthn)[ GitHub Sponsors](https://github.com/asbiin)[ RSS](/packages/muyaedward-laravel-webauthn/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (21)Versions (2)Used By (0)

Webauthn adapter for Laravel
=============================

[](#webauthn-adapter-for-laravel-)

[![Latest Version](https://camo.githubusercontent.com/f147622e3ea07928de608ef353a59394b49d622b5e54e77fbe9e7ac22167d75d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f61736269696e2f6c61726176656c2d776562617574686e2e7376673f7374796c653d666c61742d737175617265266c6162656c3d4c617465737425323056657273696f6e)](https://github.com/asbiin/laravel-webauthn/releases)[![Downloads](https://camo.githubusercontent.com/99e4897d9898db81b4bc9b2d4b6f48a4d1c0ad9fe9eebb22852a3e5e6d22a995/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f61736269696e2f6c61726176656c2d776562617574686e2e7376673f7374796c653d666c61742d737175617265266c6162656c3d446f776e6c6f616473)](https://packagist.org/packages/asbiin/laravel-webauthn)[![Workflow Status](https://camo.githubusercontent.com/13fa5c239f273788d9bad43b09d7da0f2b65e8ff47e48bd3b859299646234299/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f61736269696e2f6c61726176656c2d776562617574686e2f74657374732e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6162656c3d576f726b666c6f77253230537461747573)](https://github.com/asbiin/laravel-webauthn/actions?query=branch%3Amain)[![Quality Gate](https://camo.githubusercontent.com/5d43bd0d8b78120255342cf0c5d9d02f3a2bdb605c3d3591e96d91a12158d81a/68747470733a2f2f696d672e736869656c64732e696f2f736f6e61722f7175616c6974795f676174652f61736269696e5f6c61726176656c2d776562617574686e3f7365727665723d6874747073253341253246253246736f6e6172636c6f75642e696f267374796c653d666c61742d737175617265266c6162656c3d5175616c69747925323047617465)](https://sonarcloud.io/dashboard?id=asbiin_laravel-webauthn)[![Coverage Status](https://camo.githubusercontent.com/29e01a0792464f7e6bd6b274d5c7b92e955068426eee2c13c05a5ff6150a3310/68747470733a2f2f696d672e736869656c64732e696f2f736f6e61722f636f7665726167652f61736269696e5f6c61726176656c2d776562617574686e3f7365727665723d6874747073253341253246253246736f6e6172636c6f75642e696f267374796c653d666c61742d737175617265266c6162656c3d436f766572616765253230537461747573)](https://sonarcloud.io/dashboard?id=asbiin_laravel-webauthn)

- [Features](#features)
- [Installation](#installation)
    - [Configuration](#configuration)
- [Set Up](#set-up)
    - [Option 1: add LaravelWebauthn middleware](#option-1-add-laravelwebauthn-middleware)
        - [Login via remember](#login-via-remember)
    - [Option 2: Passwordless authentication](#option-2-passwordless-authentication)
    - [Disabling Views](#disabling-views)
    - [Cache](#cache)
- [Usage](#usage)
    - [Authenticate](#authenticate)
    - [Register a new key](#register-a-new-key)
    - [Routes](#routes)
        - [Ignore route creation](#ignore-route-creation)
    - [Customizing The Authentication Pipeline](#customizing-the-authentication-pipeline)
    - [Rate Limiter](#rate-limiter)
    - [Events](#events)
    - [View response](#view-response)
- [Compatibility](#compatibility)
    - [Laravel compatibility](#laravel-compatibility)
    - [Browser compatibility](#browser-compatibility)
        - [Homestead](#homestead)
- [License](#license)

**LaravelWebauthn** is the adapter to use Webauthn as [2FA](https://en.wikipedia.org/wiki/Multi-factor_authentication) (two-factor authentication) or as passwordless authentication on Laravel.

**Try this now on the [demo application](https://webauthn.asbin.net/).**

Features
========

[](#features)

- Manage Webauthn keys registration
- 2nd factor authentication: add a middleware service to use a Webauthn key as 2FA
- Login provider using a Webauthn key, without password

Installation
============

[](#installation)

Install this package with:

```
composer require asbiin/laravel-webauthn
```

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

[](#configuration)

You can publish LaravelWebauthn configuration in a file named `config/webauthn.php`, and resources using the `vendor:publish` command:

```
php artisan vendor:publish --provider="LaravelWebauthn\WebauthnServiceProvider"
```

Next, you should migrate your database:

```
php artisan migrate
```

Set Up
======

[](#set-up)

Option 1: add LaravelWebauthn middleware
----------------------------------------

[](#option-1-add-laravelwebauthn-middleware)

The Webauthn middleware will force the user to authenticate their webauthn key for certain routes.

Assign the middleware to a route or a group of routes:

```
use LaravelWebauthn\Http\Middleware\WebauthnMiddleware;

Route::get('/home', function () {
    // ...
})->middleware(WebauthnMiddleware::class);
```

The Webauthn middleware will redirect the user to the webauthn login page when required.

### Login via remember

[](#login-via-remember)

When session expires, but the user have set the `remember` cookie, you can revalidate webauthn session by subscribing to the `LaravelWebauthn\Listeners\LoginViaRemember` listener:

```
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Event::listen(
            \Illuminate\Auth\Events\Login::class,
            \LaravelWebauthn\Listeners\LoginViaRemember::class
        );
    }
}
```

Option 2: Passwordless authentication
-------------------------------------

[](#option-2-passwordless-authentication)

You can use Webauthn to authenticate a user without a password, using only a webauthn key authentication.

To enable passwordless authentication, first add the webauthn user provider: update your `config/auth.php` file and change the `users` provider:

```
'providers' => [
    'users' => [
        'driver' => 'webauthn',
        'model' => App\Models\User::class,
    ],
],
```

Then allow your login page to initiate a webauthn login with an `email` identifier.

You can call `webauthn.auth.options` route with a POST request and an `email` input to get the challenge data. See [authentication](#Authenticate) section for more details.

Disabling Views
---------------

[](#disabling-views)

By default LaravelWebauthn defines routes that are intended to return views for authentication and register key.

However, if you are building a JavaScript driven single-page application, you may not need these routes. For that reason, you may disable these routes entirely by setting the `views` configuration value within your application's `config/webauthn.php` configuration file to false:

```
'views' => false,
```

Cache
-----

[](#cache)

Note this package uses the cache to store the challenge data between the server request and the browser response. You'll need to setup a real cache driver from your `config/cache.php` file, and thus you can't use the `array` or `null` driver.

Usage
=====

[](#usage)

You will find an example of usage on [asbiin/laravel-webauthn-example](https://github.com/asbiin/laravel-webauthn-example). You can try it right now on the [demo application](https://webauthn.asbin.net/).

Authenticate
------------

[](#authenticate)

To authenticate with a webauthn key, the workflow is the following:

1. Open the `webauthn.login` login page. You can customize the login page view by calling `Webauthn::loginViewResponseUsing`. See [View response](#view-response)

    The default behavior will open the [webauthn::authenticate](/resources/views/authenticate.blade.php) page. You can also change the value of `webauthn.views.authenticate` in the configuration file.
2. Or: Get the publicKey challenge by calling `webauthn.auth.options` (if not provided).
3. Start the webauthn browser authentication. You can use the [`webauthn.js`](/resources/js/webauthn.js) library to do this.

    Send the signed data to `webauthn.auth` route.
4. The POST response will be:

    - a redirect response
    - or a json response with a `callback` data.

Example:

```

...

    var publicKey = {!! json_encode($publicKey) !!};

    var webauthn = new WebAuthn();

    webauthn.sign(
      publicKey,
      function (data) {
        axios.post("{{ route('webauthn.auth') }}", data)
          .then(function (response) {
            if (response.data.callback) { window.location.href = response.data.callback;}
          });
      }
    );

```

If the authentication is successful, the server will use the `webauthn.redirects.login` configuration:

- to redirect the response on a plain http call
- or with a json response, like: ```
    {
        result: true,
        callback: `webauthn.redirects.login` target url,
    }
    ```

Register a new key
------------------

[](#register-a-new-key)

To register a new webauthn key, the workflow is the following:

1. Open the `webauthn.register` page. You can customize the register page view by calling `Webauthn::registerViewResponseUsing`. See [View response](#view-response)

    The default behavior will open the [webauthn::register](/resources/views/register.blade.php) page. You can also change the value of `webauthn.views.register` in the configuration file.
2. Or: Get the publicKey challenge by calling `webauthn.store.options` (if not provided).
3. Start the webauthn browser registration. You can use the [`webauthn.js`](/resources/js/webauthn.js) library to do this.

    Send the signed data to `webauthn.store` route. The data should contain a `name` field with the webauthn key name.
4. The POST response will be:

    - a redirect response
    - or a json response with a `callback` data.

Example:

```

...

    var publicKey = {!! json_encode($publicKey) !!};

    var webauthn = new WebAuthn();

    webauthn.register(
      publicKey,
      function (data) {
        axios.post("{{ route('webauthn.store') }}", {
          ...data,
          name: "{{ $name }}",
        })
      }
    );

```

If the registration is successful, the server will use the `webauthn.redirects.register` configuration:

- to redirect the response on a plain http call
- or with a json response, like: ```
    {
        result: json serialized webauthn key value,
        callback: `webauthn.redirects.register` target url,
    }
    ```

Routes
------

[](#routes)

These routes are defined:

RequestRouteDescriptionGET `/webauthn/auth``webauthn.login`The login page.POST `/webauthn/auth/options``webauthn.auth.options`Get the publicKey and challenge to initiate a WebAuthn login.POST `/webauthn/auth``webauthn.auth`Post data after a WebAuthn login validate.GET `/webauthn/keys/create``webauthn.create`The register key page.POST `/webauthn/keys/options``webauthn.store.options`Get the publicKeys and challenge to initiate a WebAuthn registration.POST `/webauthn/keys``webauthn.store`Post data after a WebAuthn register check.DELETE `/webauthn/keys/{id}``webauthn.destroy`Delete an existing key.PUT `/webauthn/keys/{id}``webauthn.update`Update key properties (name, ...).You can customize the first part of the url by setting `prefix` value in the config file.

### Ignore route creation

[](#ignore-route-creation)

You can disable the routes creation by adding this in your `AppServiceProvider`:

```
use LaravelWebauthn\Services\Webauthn;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        Webauthn::ignoreRoutes();
    }
}
```

Customizing The Authentication Pipeline
---------------------------------------

[](#customizing-the-authentication-pipeline)

The Laravel Webauthn authentication pipeline is highly inspired by the [Fortify pipeline](https://laravel.com/docs/9.x/fortify#customizing-the-authentication-pipeline).

If you would like, you may define a custom pipeline of classes that login requests should be piped through. Each class should have an `__invoke` method which receives the incoming `Illuminate\Http\Request` instance and, like middleware, a `$next` variable that is invoked in order to pass the request to the next class in the pipeline.

To define your custom pipeline, you may use the `Webauthn::authenticateThrough` method. This method accepts a closure which should return the array of classes to pipe the login request through. Typically, this method should be called from the `boot` method of your `App\Providers\FortifyServiceProvider` class.

The example below contains the default pipeline definition that you may use as a starting point when making your own modifications:

```
use LaravelWebauthn\Actions\AttemptToAuthenticate;
use LaravelWebauthn\Actions\EnsureLoginIsNotThrottled;
use LaravelWebauthn\Actions\PrepareAuthenticatedSession;
use LaravelWebauthn\Services\Webauthn;
use Illuminate\Http\Request;

Webauthn::authenticateThrough(fn (Request $request) => array_filter([
    config('webauthn.limiters.login') !== null ? null : EnsureLoginIsNotThrottled::class,
    AttemptToAuthenticate::class,
    PrepareAuthenticatedSession::class,
]));
```

Rate Limiter
------------

[](#rate-limiter)

By default, Laravel Webauthn will throttle logins to five requests per minute for every email and IP address combination. You may specify a custom rate limiter with other specifications.

First define a custom rate limiter. Follow [Laravel rate limiter documentation](https://laravel.com/docs/11.x/routing#defining-rate-limiters) to create a new RateLimiter within the `boot` method of your application's `App\Providers\AppServiceProvider` class.

```
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    protected function boot(): void
    {
        RateLimiter::for('webauthn-login', function (Request $request) {
            return Limit::perMinute(1000);
        });
    }
}
```

Then use this new custom rate limiter in your `webauthn.limiters.login` configuration:

```
'limiters' => [
    'login' => 'webauthn-login',
],
```

Events
------

[](#events)

Events are dispatched by LaravelWebauthn:

- `\LaravelWebauthn\Events\WebauthnLogin` on login with Webauthn check.
- `\LaravelWebauthn\Events\WebauthnLoginData` on preparing authentication data challenge.
- `\Illuminate\Auth\Events\Failed` on a failed login check.
- `\LaravelWebauthn\Events\WebauthnRegister` on registering a new key.
- `\LaravelWebauthn\Events\WebauthnRegisterData` on preparing register data challenge.
- `\LaravelWebauthn\Events\WebauthnRegisterFailed` on failing registering a new key.

View response
-------------

[](#view-response)

You can easily change the view responses with the Webauthn service.

For instance, call `Webauthn::loginViewResponseUsing` in your `App\Providers\AppServiceProvider` class:

```
use LaravelWebauthn\Services\Webauthn;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        Webauthn::loginViewResponseUsing(LoginViewResponse::class);
    }
}
```

With a `LoginViewResponse` class:

```
use LaravelWebauthn\Http\Responses\LoginViewResponse as LoginViewResponseBase;

class LoginViewResponse extends LoginViewResponseBase
{
    public function toResponse($request)
    {
        return Inertia::render('Webauthn/WebauthnLogin', [
            'publicKey' => $this->publicKey
        ])->toResponse($request);
    }
}
```

List of methods and their expected response contracts:

Webauthn static methods`\LaravelWebauthn\Contracts``loginViewResponseUsing``LoginViewResponseContract``loginSuccessResponseUsing``LoginSuccessResponseContract``registerViewResponseUsing``RegisterViewResponseContract``registerSuccessResponseUsing``RegisterSuccessResponseContract``destroyViewResponseUsing``DestroyResponseContract``updateViewResponseUsing``UpdateResponseContract`Compatibility
=============

[](#compatibility)

Laravel compatibility
---------------------

[](#laravel-compatibility)

This package has the following Laravel compatibility:

Laravel[asbiin/laravel-webauthn](https://github.com/asbiin/laravel-webauthn)5.8-8.x&lt;= 1.2.07.x-8.x2.0.1&gt;= 9.x&gt;= 3.0.0Browser compatibility
---------------------

[](#browser-compatibility)

Most of the browsers [support Webauthn](https://caniuse.com/webauthn).

However, your browser will refuse to negotiate a relay to your security device without the following:

- a proper domain (localhost and 127.0.0.1 will be rejected by `webauthn.js`)
- an SSL/TLS certificate trusted by your browser (self-signed is okay)
- connected HTTPS on port 443 (ports other than 443 will be rejected)

### Homestead

[](#homestead)

If you are a Laravel Homestead user, the default is to forward ports. You can switch from NAT/port forwarding to a private network with similar `Homestead.yaml` options:

```
sites:
  - map: homestead.test
networks:
  - type: "private_network"
    ip: "192.168.254.2"
```

Re-provisioning vagrant will inform your virtual machine of the new network and install self-signed SSL/TLS certificates automatically: `vagrant reload --provision`

If you haven't done so already, describe your site domain and network in your hosts file:

```
192.168.254.2 homestead.test

```

License
=======

[](#license)

Author: [Alexis Saettler](https://github.com/asbiin)

Copyright © 2019–2024.

Licensed under the MIT License. [View license](/LICENSE.md).

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance37

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 53.6% 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

Unknown

Total

1

Last Release

569d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1068abc44a610494c51024b5a679afcaee66be85d34c9b3f5e2a44672922707e?d=identicon)[kikuyu1](/maintainers/kikuyu1)

---

Top Contributors

[![asbiin](https://avatars.githubusercontent.com/u/25419741?v=4)](https://github.com/asbiin "asbiin (140 commits)")[![dependabot-preview[bot]](https://avatars.githubusercontent.com/in/2141?v=4)](https://github.com/dependabot-preview[bot] "dependabot-preview[bot] (68 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (35 commits)")[![muyaedward](https://avatars.githubusercontent.com/u/7256186?v=4)](https://github.com/muyaedward "muyaedward (4 commits)")[![iv-craig](https://avatars.githubusercontent.com/u/8458551?v=4)](https://github.com/iv-craig "iv-craig (2 commits)")[![lbausch](https://avatars.githubusercontent.com/u/5747127?v=4)](https://github.com/lbausch "lbausch (1 commits)")[![MarkIvanowich](https://avatars.githubusercontent.com/u/4605655?v=4)](https://github.com/MarkIvanowich "MarkIvanowich (1 commits)")[![matthieutirelli](https://avatars.githubusercontent.com/u/25278098?v=4)](https://github.com/matthieutirelli "matthieutirelli (1 commits)")[![matthijs](https://avatars.githubusercontent.com/u/36565?v=4)](https://github.com/matthijs "matthijs (1 commits)")[![niels2080](https://avatars.githubusercontent.com/u/98124608?v=4)](https://github.com/niels2080 "niels2080 (1 commits)")[![peterheider](https://avatars.githubusercontent.com/u/5007777?v=4)](https://github.com/peterheider "peterheider (1 commits)")[![Aethyn](https://avatars.githubusercontent.com/u/17317620?v=4)](https://github.com/Aethyn "Aethyn (1 commits)")[![willbrowningme](https://avatars.githubusercontent.com/u/20662079?v=4)](https://github.com/willbrowningme "willbrowningme (1 commits)")[![bistory](https://avatars.githubusercontent.com/u/108102?v=4)](https://github.com/bistory "bistory (1 commits)")[![Cyb0rk](https://avatars.githubusercontent.com/u/95137?v=4)](https://github.com/Cyb0rk "Cyb0rk (1 commits)")[![developStorm](https://avatars.githubusercontent.com/u/59678453?v=4)](https://github.com/developStorm "developStorm (1 commits)")[![krsriq](https://avatars.githubusercontent.com/u/2337648?v=4)](https://github.com/krsriq "krsriq (1 commits)")

---

Tags

phplaravelsecuritywebauthn

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/muyaedward-laravel-webauthn/health.svg)

```
[![Health](https://phpackages.com/badges/muyaedward-laravel-webauthn/health.svg)](https://phpackages.com/packages/muyaedward-laravel-webauthn)
```

###  Alternatives

[asbiin/laravel-webauthn

Laravel Webauthn support

309574.8k](/packages/asbiin-laravel-webauthn)[craftcms/cms

Craft CMS

3.6k3.6M2.6k](/packages/craftcms-cms)[web-auth/webauthn-lib

FIDO2/Webauthn Support For PHP

1195.3M72](/packages/web-auth-webauthn-lib)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

50570.7k1](/packages/web-auth-webauthn-framework)[tzsk/otp

A secure, database-free One-Time Password (OTP) generator and verifier for PHP and Laravel.

241641.4k1](/packages/tzsk-otp)[skydiver/laravel-route-blocker

Block routes by IP

8272.4k](/packages/skydiver-laravel-route-blocker)

PHPackages © 2026

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