web-auth/webauthn-lib
PHP WebAuthn library for adding passkeys/FIDO2 authentication to apps and APIs. Implements registration and login flows, credential validation, and related WebAuthn data structures, suitable for Laravel or custom frameworks.
Start by installing the package via Composer: composer require web-auth/webauthn-lib. Review the README.md for initial setup—focus on the registration and authentication flow examples. Begin with a minimal implementation:
PublicKeyCredentialCreationOptionsGenerator to create registration options (sent to frontend)PublicKeyCredentialParser to decode the response from the browserPublicKeyCredentialSourceValidator and a temporary in-memory repository (InMemoryPublicKeyCredentialSourceRepository)CredentialRepositoryInterface implementation to persist credentials.Implement WebAuthn in two discrete, idempotent flows:
Registration Flow
CreateCredentialOptions (include user.id, user.name, challenge)navigator.credentials.create()PublicKeyCredential → parse with PublicKeyCredentialParserPublicKeyCredentialSource (store credentialId, publicKey, signCount, aaguid, attestationType) via your repositoryAuthentication Flow
GetCredentialOptions (include challenge, allowed credentialIds)navigator.credentials.get()signCount against stored credentialIntegrate via a dedicated WebAuthnService class that encapsulates both flows. Use Laravel’s Auth contract to bridge—e.g., create a WebAuthnGuard or custom UserProvider that authenticates users by credential ID. For storage, extend DefaultPublicKeyCredentialSourceRepository to persist to Eloquent models with columns: credential_id (string), public_key (json), sign_count (int), transports (json), created_at.
https://app.example.test → RP ID example.test fails; use app.example.test or run tests with localhost (allowed by spec) for dev. Double-check $_SERVER['HTTP_ORIGIN'] vs your configured RP ID.credentialId, attestationStatement) use base64url. Use Base64Url::encode() / decode() helpers from the package—but note internal COSE keys are binary.requireUserVerification: false in GetCredentialOptions.signCount monotonicity is critical: The authenticator increments this—your validator must reject assertions where the new signCount ≤ stored value (ignoring wraparound). Track it per credential in DB.localhost. Use php artisan serve (Laravel’s dev server) + ngrok for local HTTPS, or use web-auth’s test fixtures (MockRegistration, MockAuthentication) for unit tests.u2fappId, credProps), but advanced ones (e.g., largeBlob, hue) require manual parsing—check PublicKeyCredential::getClientExtensionResults().How can I help you explore Laravel packages today?