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

Laravel Webauthn Laravel Package

asbiin/laravel-webauthn

asbiin/laravel-webauthn brings passwordless WebAuthn authentication to Laravel. Let users register security keys, Touch ID, Face ID, or Windows Hello and sign in without passwords using simple routes, middleware, and configurable user models.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. composer require asbiin/laravel-webauthn
  2. Publish and run the migration: php artisan vendor:publish --tag=webauthn-migrations && php artisan migrate (creates the webauthn_keys table).
  3. Publish the config: php artisan vendor:publish --tag=webauthn-config — this is the first file to open.
  4. Add the WebauthnAuthenticatable trait to your User model (it provides the webAuthnCredentials() relation).
  5. On the frontend, install @simplewebauthn/browser and feed the JSON options from your endpoints into startRegistration() / startAuthentication().

Where to look first: config/webauthn.php (routes, rp_id, origins, middleware), the Webauthn facade (LaravelWebauthn\Facades\Webauthn), and the default WebauthnRegisterController / WebauthnLoginController shipped by the package.

First use case: add WebAuthn as a second factor behind an existing password login. Hit the built-in /webauthn/register flow to enroll a key, then gate sensitive routes behind the assertion flow. Only reach for custom controllers once the default flow works end to end.

Implementation Patterns

  • Registration (enroll a key). Two endpoints: a GET that returns Webauthn::generateAttestationOptions($user) as JSON, and a POST that calls Webauthn::validateAttestation($user, $request->input('response')) and persists the returned CredentialRecord. The package's default controller already handles persistence via the trait relation.
  • Authentication / step-up. GET returns Webauthn::generateAssertionOptions($user); POST calls Webauthn::validateAssertion($user, $request->input('response')). On success, Auth::login($user) and session()->regenerate(). Reuse the same assertion flow for "confirm before deleting account" style step-up screens.
  • Custom controllers. Copy the package controllers into your app when you need rate limiting, custom redirects, audit events, or branded responses. Keep the two-phase challenge → validate shape intact; don't try to validate in the same request that generated the options.
  • Multiple keys per user. The schema supports many credentials per user. Build a "manage my devices" page off $user->webAuthnCredentials; deleting a row is a normal Eloquent delete.
  • Blade/JS glue. Publish the package views with --tag=webauthn-views, or @json($options) into your own. Remember to base64url-decode challenge and user.id before passing them to startRegistration / startAuthentication.
  • v6 shape. Treat the return value of validateAttestation() / validateAssertion() as a CredentialRecord value object and read it only through getters (see Gotchas) — this is the main behavioural change custom integrations need to absorb.

Gotchas and Tips

  • v6.0.0 breaking change. validateAttestation() / validateAssertion() now return a CredentialRecord (webauthn-lib 5.3) instead of the deprecated PublicKeyCredentialSource. Property access becomes method calls: ->publicKeyCredentialId → ->getPublicKeyCredentialId(), ->userHandle → ->getUserHandle(), ->credentialPublicKey → ->getPublicKey(), ->counter → ->getCounter(), ->transports → ->getTransports(), ->aaguid → ->getAaguid(). Apps using only the built-in controllers will upgrade without touching code; only custom code that inspected the returned object needs editing. Upgrade path: composer update, then grep for PublicKeyCredentialSource and for -> access on validate results. DB schema and JS are unchanged.
  • Secure context required. WebAuthn only runs on HTTPS (or localhost). rp_id and origin values in config/webauthn.php must match the browser origin exactly; a mismatch surfaces as an opaque DOMException in JS, not a PHP error.
  • Challenge lifecycle. Challenges are single-use and session-bound. "Challenge not found" or signature failures usually mean a session driver / cookie domain mismatch, a stale session across a redirect, or a replayed request — not a crypto bug.
  • Stable user handles. For discoverable credentials the user handle must map back to a user. Keep it stable (the package uses the user id by default); changing it silently invalidates every existing passkey.
  • Testing. Real ceremonies can't be completed headlessly. Mock the Webauthn facade (or bind a fake) and assert on your controller's redirect/session behaviour; use the package's own test suite as a template for stubbing validate calls.
  • Extension points. You can override the credential model/repository and the trait relation via config if you need extra columns (nickname, last-used timestamp). Add a last_used_at column and touch it in a listener around the assert flow.
  • Debugging. Log the raw options and the raw client response and compare shapes. Most production failures are JSON shape (ArrayBuffer vs base64url), origin/RP-ID drift, or reused challenges — not the library. The browser's WebAuthn panel in devtools is the fastest way to see what was actually sent.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle