Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Passkey Bundle Laravel Package

mulertech/passkey-bundle

mulertech/passkey-bundle adds passwordless passkey authentication to Laravel and PHP applications. It handles WebAuthn registration and login flows, letting users sign in with device biometrics or security keys for faster, phishing-resistant access and simpler integration.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require and run whatever the README's install command is (config publish, migrations for the credential table, and a JS entrypoint registered through Vite). The package is a thin Laravel wrapper over the browser's WebAuthn API, so most of the setup cost is config, not code.
  • Look first at the published config file. The relying party ID and origin are the two values that break everything if they are even slightly wrong, and they are the first thing to check when a ceremony fails silently.
  • Then look at the shipped Blade/JS entrypoint. The package exposes buttons plus a small module that binds behaviour; understanding that binding model is the difference between a smooth integration and an afternoon of debugging.
  • First use case to ship: a "Sign in with a passkey" button on the existing login page, alongside password auth. It is additive, needs no changes to your user table beyond the package's trait/migration, and gives you an end-to-end ceremony to validate config against.
  • Second use case: enrollment from the account settings page, so existing users can add a passkey before you make it the primary path.

Implementation Patterns

  • Treat the button as a plain Blade element. Drop it into a partial, a Livewire component, or a Turbo frame as you normally would — since v2.0.1 the module resolves clicks via a single delegated listener on document, so markup can be replaced at any time without rebinding anything.
  • Keep the asset loaded exactly once, through your normal Vite entrypoint. Do not write your own querySelectorAll + addEventListener initialiser for the buttons; that was the pattern the package itself moved away from, and duplicating it will reintroduce the class of bug v2.0.1 fixed.
  • For multi-button pages, rely on the button resolving its own container. Render each ceremony inside its own wrapper (registration in settings, authentication on login) and let the delegated handler figure out which flow the click belongs to. This keeps you from threading IDs through your Blade templates.
  • Registration flow: click → browser prompt → POST attestation to the package's endpoint → credential stored → redirect. Hook your own post-registration behaviour (flash message, redirect to a specific page, dispatch an event) at the redirect/response level rather than by patching the JS.
  • Authentication flow: click → browser prompt → POST assertion → the package's guard logs the user in. If you have custom logic (2FA interaction, remember-me, redirect to intended URL), layer it on the controller/route the package publishes rather than forking the JavaScript.
  • In a Turbo/Livewire SPA-ish setup, keep the button inside whatever gets morphed and let the document listener do the work. The same applies to wire:navigate and any other morphing navigation — the delegated listener is the integration point, not your component lifecycle hooks.
  • For tests, assert at the HTTP layer: the challenge endpoint returns a well-formed challenge, the verification endpoint rejects a malformed payload, and a successful assertion authenticates the expected user. Driving the real WebAuthn prompt in a browser test requires a virtual authenticator (Chrome DevTools Protocol), so plan for that separately.

Gotchas and Tips

  • The v2.0.1 bug is the one to know about. Before it, buttons were bound at module-evaluation time. Because the browser's module map means a module is only evaluated once per page, any navigation that replaced the DOM (Turbo, morphing equivalents) left the new buttons bound to nothing — clicks did absolutely nothing and no error was thrown anywhere. If you are on 2.0.0, upgrade; it is a plain composer update with no config changes.
  • If you previously worked around that bug with your own re-init-on-navigation code, delete it after upgrading. You will otherwise end up with double handling.
  • Silent failure is the default failure mode. A ceremony that never starts looks identical to a click handler that never ran. When debugging, check in this order: is the asset actually loaded (network tab), did the module evaluate (a console log or breakpoint on the imported entry), and are the button's data attributes present and correct in the live DOM.
  • Relying party ID and origin must match the page exactly — including subdomains, scheme, and port. https://example.com and https://www.example.com are not interchangeable. Localhost is the exception that works over plain HTTP.
  • The credential flow requires a secure context. A test/staging environment served over HTTP on a non-localhost hostname will fail in ways that look like code bugs.
  • The document-level listener is per-page-load, so it does not leak across navigations, but it also means you should not try to "teardown" it in a component unmount hook. There is nothing to tear down.
  • Extension points worth knowing: the published config (RP ID, origin, user verification policy), the published views (swap the button markup, add your own styling/loading states), and the published routes/controller (custom redirects, custom guards). Prefer these over monkey-patching the JS module.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings