Security Advanced Auth - v1.0.0
WebAuthn / FIDO2
WebAuthnManager (577 lines) handles registration + authentication ceremonies for passkeys, security keys, and platform authenticators. The package ships interface-level — the actual WebAuthn library is the consumer's choice. Wire a concrete implementation in your service provider.
Endpoints
| Method | Path | Controller method |
|---|---|---|
| POST | /auth/webauthn/register/options |
WebAuthnController::registerOptions |
| POST | /auth/webauthn/register/verify |
WebAuthnController::registerVerify |
| POST | /auth/webauthn/authenticate/options |
WebAuthnController::authenticateOptions |
| POST | /auth/webauthn/authenticate/verify |
WebAuthnController::authenticateVerify |
Prefix and middleware configurable in config('artisanpack.security-advanced-auth.routes.webauthn').
Registration flow
- User triggers "Add passkey" in the UI (
WebAuthnCredentialsManagerLivewire component). - Component dispatches
start-webauthn-registration. - Host JS fetches options:
POST /auth/webauthn/register/options. - Host JS calls
navigator.credentials.create({publicKey: options}). - Browser shows the authenticator prompt; user authenticates.
- Host JS POSTs the response to
/auth/webauthn/register/verify. - Server stores the credential as a
WebAuthnCredentialrow.
Authentication flow
- Login form presents "Sign in with passkey" alongside password.
- Host JS fetches:
POST /auth/webauthn/authenticate/options. Passuser_idor omit for discovery flows. - Host JS calls
navigator.credentials.get({publicKey: options}). - Host JS POSTs the response to
/auth/webauthn/authenticate/verify. - Server verifies, returns user info, logs the user in.
Programmatic API
use ArtisanPackUI\SecurityAdvancedAuth\Authentication\WebAuthn\WebAuthnManager;
$manager = app( WebAuthnManager::class );
// Registration
$options = $manager->generateRegistrationOptions( $user, [/* options */] );
$result = $manager->verifyRegistration( $user, $response, $challenge );
// Authentication
$options = $manager->generateAuthenticationOptions( $user );
$result = $manager->verifyAuthentication( $response, $challenge );
// Credential management
$creds = $manager->getCredentials( $user ); // Collection<WebAuthnCredential>
$manager->deleteCredential( $user, $credentialId );
$manager->updateCredential( $user, $credentialId, ['name' => 'New name'] );
Passwordless / discovery
generateAuthenticationOptions(null) produces options without a specific user — the browser surfaces all stored passkeys and the user picks. Useful for "sign in with passkey" buttons that don't ask for username first.
Relying Party
The Relying Party ID is your app's domain (e.g. app.example.com). Configure in config('artisanpack.security-advanced-auth.webauthn.relying_party') — defaults derive from APP_URL.
The RP ID is locked at registration time. Changing it later invalidates all existing credentials. Be deliberate about this in production.
Live tests / e2e
For server-side flow tests, mock the underlying WebAuthn library. For browser-driven tests, virtual authenticators let Playwright / Cypress simulate the authenticator without needing physical hardware.