spatie/laravel-passkeys
Spatie's Laravel Passkeys package adds passwordless login to Laravel apps, with a Livewire component for generating and storing passkeys on user devices and a Blade component for authenticating users with those passkeys.
Architecture fit. spatie/laravel-passkeys is a Laravel-native wrapper around web-auth/webauthn-lib that exposes WebAuthn registration and authentication ceremonies through Livewire and Blade components, with the underlying ceremony logic factored into action classes (GeneratePasskeyRegisterOptions, authenticateWithPasskey, and a configurable ceremony step manager added in 1.5.0). It fits best in a server-rendered Laravel monolith using Blade + Livewire, where the registration UI lives in an account-settings screen and the login component is dropped into the existing auth view. It is not a framework-agnostic WebAuthn library: for an Inertia/React/Vue frontend or an API-only service, the package's value reduces to its action classes, and the team will own the JSON endpoints, session/ceremony state, and client-side navigator.credentials plumbing themselves. The changelog indicates Inertia usage is documented, but the first-class, maintained UX surface is Livewire.
Integration feasibility. The install path is standard Spatie: Composer require, publish config and migration, add a trait/model relationship for credentials, mount the Livewire component for enrollment and the Blade component for login. The hard part is not code volume but correctness of the WebAuthn environment: HTTPS everywhere, an accurate Relying Party ID, and origin allowlisting. allowedOrigins became configurable in 1.3.0, which is the unlock for staging domains, preview environments, and multi-domain deployments — without it, most non-trivial hosting topologies break. A reasonable estimate is 1–2 sprints for a mid-level Laravel developer, most of it spent on UX, recovery flows, and cross-browser testing rather than the package itself.
Technical risk. Three categories matter. First, upstream dependency churn: 1.6.1, 1.6.4, and 1.6.5 were all released to track web-auth/webauthn-lib changes, including a PublicKeyCredentialSource → CredentialRecord type shift that produced runtime type errors. That is a signal to pin versions deliberately and read changelogs before minor bumps. Second, coupling: the package expects Livewire (3 and 4 are supported in dev dependencies as of 1.6.0), so it inherits Livewire's request lifecycle and version constraints. Third, product risk: no built-in account recovery, attestation policy, or step-up/fallback orchestration — those are your responsibility, and they are where most passkey rollouts actually fail. The adoption signal is mixed: 475 stars and active Spatie maintenance, translation PRs, and recent feature work (remember-me, configurable origins, ceremony manager) suggest real usage, while the reported zero dependents means limited public evidence of production deployments to borrow confidence from.
Key questions.
Stack fit. Laravel 10–13, PHP 8.x, Livewire 3/4, and web-auth/webauthn-lib 5.3.x are the supported envelope per the changelog. It slots into Breeze/Jetstream-style auth scaffolding with minor view overrides, and coexists cleanly with Laravel's existing session guards and "remember me" (supported since 1.4.0 via authenticateWithPasskey). It does not replace Laravel's auth system; it adds a credential type and a login ceremony on top of it.
Migration path. Additive and reversible. A new passkeys table and a user trait are the only schema-level changes; no backfill or user-data migration is required. The lowest-risk sequence is to ship passkeys as an opt-in convenience alongside passwords, measure enrollment and login success, and only then consider making passkey-first the default. Feature-flag the enrollment UI so it can be withdrawn without touching login.
Compatibility. Two sharp edges. Origin/RP ID configuration must be correct per environment, and preview or per-tenant domains must be explicitly allowlisted. Second, frontend compatibility: if the product is Inertia/SPA, budget for custom controllers around the action classes and treat the Livewire components as reference implementations rather than drop-ins. Browser support for conditional UI/autofill differs across Safari, Chrome, and Firefox, so a compatibility matrix and a graceful password fallback are prerequisites, not nice-to-haves.
Sequencing.
Maintenance. Low ongoing code maintenance, moderate dependency vigilance. The package tracks an active upstream (webauthn-lib), and recent patch releases exist specifically to absorb upstream type and deprecation changes. Pin the dependency, subscribe to releases, and schedule a quarterly upgrade window rather than allowing unattended composer update drift in auth-critical code.
Support. The support burden migrates from "I forgot my password" to "my passkey isn't offered on this device," "my credential didn't sync between my phone and laptop," and "I lost the device." These are answerable only with a documented recovery path and a support tool that can enumerate and revoke a user's registered credentials. Localization is effectively solved out of the box — the changelog shows a dozen-plus language contributions — which reduces one class of helpdesk tickets.
Scaling. Essentially free. The server is stateless apart from credential rows and per-ceremony state in the session; there is no external identity SaaS dependency, no per-authentication vendor cost, and no meaningful throughput impact. The only scaling concern is database growth of credential records, which is trivial at typical user volumes.
Failure modes. Environment misconfiguration (wrong RP ID or origin) causes hard registration/authentication rejections that look like bugs to users. Non-HTTPS or mixed-content contexts fail silently in some browsers. Stale or lost ceremony state — session expiry, Livewire request failure mid-ceremony, load-balanced setups without sticky sessions or shared session storage — produces intermittent, hard-to-reproduce errors. Upstream library upgrades can surface as runtime type errors (as in the 5.3 CredentialRecord transition). Lost-device lockout is the highest-severity user-facing failure and is entirely a product decision rather than a package capability. Finally, low adoption is itself a failure mode: if conditional UI isn't surfaced on the login page, most users will never discover passkeys exist.
Ramp-up. A mid-level Laravel developer can be productive in days; the package abstracts most of the ceremony complexity. The team still needs working knowledge of RP ID, challenges, user verification, resident keys, and authenticator selection — the 1.1.0 addition of authenticator selection criteria to GeneratePasskeyRegisterOptions is exactly the knob most teams will need to reason about, so plan for a short internal primer plus a written decision record on those policies before shipping.
How can I help you explore Laravel packages today?