Components
st-passkey-register
A WebAuthn passkey registration component that handles the full passkey creation flow with your Laravel backend.
Basic Usage
Wrap a form with <st-passkey-register> and specify your API endpoints:
<st-passkey-register
options-endpoint="/passkey/register/options"
store-endpoint="/passkey/register"
>
<form>
<input type="text" name="name" placeholder="Passkey name">
<button type="submit">Register Passkey</button>
<p data-passkey-error hidden class="text-red-500"></p>
</form>
</st-passkey-register>
How It Works
- User submits the form
- Component POSTs form data to
options-endpointto get WebAuthn options - Browser prompts user to create a passkey (biometric/security key)
- Component POSTs the credential to
store-endpoint - On success, redirects to
Locationheader or reloads the page
Attributes
| Attribute | Required | Description |
|---|---|---|
| options-endpoint | Yes | URL that returns WebAuthn PublicKeyCredentialCreationOptions |
| store-endpoint | Yes | URL to POST the created credential for storage |
Laravel Backend
Your Laravel backend needs two endpoints. Here's an example using webauthn-lib:
// routes/web.php
Route::post('/passkey/register/options', [PasskeyController::class, 'options']);
Route::post('/passkey/register', [PasskeyController::class, 'store']);
The options endpoint should return JSON matching the WebAuthn spec:
{
"challenge": "base64url-encoded-challenge",
"rp": { "name": "My App", "id": "example.com" },
"user": {
"id": "base64url-encoded-user-id",
"name": "user@example.com",
"displayName": "John Doe"
},
"pubKeyCredParams": [
{ "type": "public-key", "alg": -7 },
{ "type": "public-key", "alg": -257 }
],
"timeout": 60000,
"authenticatorSelection": {
"residentKey": "required",
"userVerification": "required"
}
}
Error Display
Add an element with data-passkey-error to display errors:
<p data-passkey-error hidden class="text-sm text-red-500 mt-2"></p>
The component will populate this with error messages and remove the hidden attribute.
Events
| Event | Detail |
|---|---|
| st-passkey-register:start | Registration flow started |
| st-passkey-register:success | { response } - Server response after storing credential |
| st-passkey-register:error | { stage, error } - Error with stage (options/create/store) |
| st-passkey-register:cancel | User cancelled the passkey prompt |
const register = document.querySelector('st-passkey-register')
register.addEventListener('st-passkey-register:success', (e) => {
console.log('Passkey registered:', e.detail.response)
})
register.addEventListener('st-passkey-register:error', (e) => {
console.error(`Error at ${e.detail.stage}:`, e.detail.error)
})
Loading State
The component sets data-loading="true" during registration and disables the submit button:
st-passkey-register[data-loading="true"] button[type="submit"] {
opacity: 0.5;
cursor: wait;
}
CSRF Protection
The component automatically includes the CSRF token from either:
<meta name="csrf-token" content="...">in the document head<input name="_token" value="...">inside the form
Browser Support
WebAuthn is supported in all modern browsers. If the browser doesn't support passkeys, the component:
- Displays "Your browser does not support passkeys" in the error element
- Disables the submit button
Programmatic Registration
You can trigger registration programmatically:
const register = document.querySelector('st-passkey-register')
await register.register()