From 802505f795da172dd4461ae64c9928d326fa0c20 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Wed, 8 Apr 2026 10:53:32 +0100 Subject: [PATCH 1/2] wip --- .../tags/user-delete_passkey_form.md | 63 ++++++++++ content/collections/tags/user-login_form.md | 58 +++++++++ content/collections/tags/user-passkey_form.md | 113 ++++++++++++++++++ content/collections/tags/user-passkeys.md | 97 +++++++++++++++ 4 files changed, 331 insertions(+) create mode 100644 content/collections/tags/user-delete_passkey_form.md create mode 100644 content/collections/tags/user-passkey_form.md create mode 100644 content/collections/tags/user-passkeys.md diff --git a/content/collections/tags/user-delete_passkey_form.md b/content/collections/tags/user-delete_passkey_form.md new file mode 100644 index 000000000..ab55559c9 --- /dev/null +++ b/content/collections/tags/user-delete_passkey_form.md @@ -0,0 +1,63 @@ +--- +id: d0ed4ac0-536a-47a1-965b-202b52baddb2 +blueprint: tag +title: 'User:Delete_Passkey_Form' +description: 'Creates a form to delete a passkey' +intro: 'As the tag name suggests, it allows you to delete a passkey.' +parameters: + - + name: id + type: string + description: 'The passkey ID to delete. Required.' + - + name: redirect + type: string + description: Where the user should be taken after successfully deleting a passkey. + - + name: HTML Attributes + type: + description: 'Set HTML attributes as if you were in an HTML element. For example, `class="delete-form"`.' +related_entries: + - 38323438-4719-4a7b-ba5a-8abfe0d7dfc0 + - 7a958307-4cdb-47f3-a689-0c7de57e3ff7 + - 7432f1cb-7418-4d54-8e65-51b1ae3bcb3a +--- +## Overview + +The `user:delete_passkey_form` tag renders a form to delete a passkey. + +### Example + +The tag is typically used inside a [`{{ user:passkeys }}`](/tags/user-passkeys) loop: + +::tabs + +::tab antlers +```antlers +{{ user:passkeys as="passkeys" }} + {{ passkeys }} +
+ {{ name }} + + {{ user:delete_passkey_form :id="id" }} + + {{ /user:delete_passkey_form }} +
+ {{ /passkeys }} +{{ /user:passkeys }} +``` +::tab blade +```blade + + @foreach ($passkeys as $passkey) +
+ {{ $passkey['name'] }} + + + + +
+ @endforeach +
+``` +:: diff --git a/content/collections/tags/user-login_form.md b/content/collections/tags/user-login_form.md index 061bfa3fe..8c02c8202 100644 --- a/content/collections/tags/user-login_form.md +++ b/content/collections/tags/user-login_form.md @@ -34,6 +34,18 @@ variables: name: success type: string description: A success message. + - + name: passkeys_enabled + type: boolean + description: Whether passkey authentication is configured. + - + name: passkey_options_url + type: string + description: URL to fetch WebAuthn assertion options for passkey login. + - + name: passkey_verify_url + type: string + description: URL to verify passkey login. id: 7432f1cb-7418-4d54-8e65-51b1ae3bcb3a --- ## Overview @@ -101,3 +113,49 @@ The tag will render the opening and closing `
` HTML elements for you. The ``` :: + +## Passkeys + +You can add passkey authentication to your login form using Statamic's frontend JavaScript helpers. + +1. First, include the helpers script on your page: + ```html + + ``` + +2. Use the provided variables to add a passkey login option: + ```antlers + {{ user:login_form }} + + + + + {{ if passkeys_enabled }} {{# [tl! focus:start] #}} + + + + {{ /if }} {{# [tl! focus:end] #}} + {{ /user:login_form }} + ``` +3. Add `autocomplete="username webauthn"` to your email input for browser autofill to work. + +For more information on managing passkeys on the frontend, see the following docs: +- [`{{ user:passkeys }}`](/tags/user-passkeys) +- [`{{ user:passkey_form }}`](/tags/user-passkey_form) +- [`{{ user:delete_passkey_form }}`](/tags/user-delete_passkey_form) diff --git a/content/collections/tags/user-passkey_form.md b/content/collections/tags/user-passkey_form.md new file mode 100644 index 000000000..f2fc21969 --- /dev/null +++ b/content/collections/tags/user-passkey_form.md @@ -0,0 +1,113 @@ +--- +id: 7a958307-4cdb-47f3-a689-0c7de57e3ff7 +blueprint: tag +title: 'User:Passkey_Form' +description: 'Creates a passkey registration form' +intro: 'Allows authenticated users to set up passkeys' +variables: + - + name: create_url + type: string + description: 'URL to fetch WebAuthn attestation options for creating a new passkey.' + - + name: store_url + type: string + description: 'URL to store the new passkey after registration.' + - + name: errors + type: array + description: An array of validation errors. + - + name: success + type: string + description: A success message. +related_entries: + - 38323438-4719-4a7b-ba5a-8abfe0d7dfc0 + - d0ed4ac0-536a-47a1-965b-202b52baddb2 + - 7432f1cb-7418-4d54-8e65-51b1ae3bcb3a +--- +## Overview + +The `user:passkey_form` tag provides the necessary URLs to set up passkeys for authenticated users. + +### JavaScript helpers + +You'll need to include the frontend helpers script on your page: + +```html + +``` + +### Example + +::tabs + +::tab antlers +```antlers +{{ user:passkey_form }} + + + + {{ if success }} +

Passkey created successfully!

+ {{ /if }} + + {{ if errors }} + + {{ /if }} + + +{{ /user:passkey_form }} +``` +::tab blade +```blade + + + + + @if ($success) +

Passkey created successfully!

+ @endif + + @if ($errors) +
    + @foreach ($errors as $error) +
  • {{ $error }}
  • + @endforeach +
+ @endif + + +
+``` +:: diff --git a/content/collections/tags/user-passkeys.md b/content/collections/tags/user-passkeys.md new file mode 100644 index 000000000..df65f0abb --- /dev/null +++ b/content/collections/tags/user-passkeys.md @@ -0,0 +1,97 @@ +--- +id: 38323438-4719-4a7b-ba5a-8abfe0d7dfc0 +blueprint: tag +title: 'User:Passkeys' +description: 'Lists the current user''s passkeys' +intro: 'Loop through the authenticated user''s registered passkeys.' +variables: + - + name: id + type: string + description: 'The passkey identifier.' + - + name: name + type: string + description: 'The user-defined passkey name.' + - + name: last_login + type: Carbon + description: 'The last time the passkey was used for login, or null if never used.' +related_entries: + - 7432f1cb-7418-4d54-8e65-51b1ae3bcb3a + - 7a958307-4cdb-47f3-a689-0c7de57e3ff7 + - d0ed4ac0-536a-47a1-965b-202b52baddb2 +--- +## Overview + +The `user:passkeys` tag loops through the user's passkeys. Useful for building a passkey management page where users can view and delete their passkeys. + +### Example + +::tabs + +::tab antlers +```antlers +{{ user:passkeys as="passkeys" }} + {{ if passkeys }} +

Your Passkeys

+ + {{ else }} +

You haven't set up any passkeys yet.

+ {{ /if }} +{{ /user:passkeys }} +``` +::tab blade +```blade + + @if ($passkeys) +

Your Passkeys

+
    + @foreach ($passkeys as $passkey) +
  • + {{ $passkey['name'] }} + @if ($passkey['last_login']) + Last used: {{ $passkey['last_login']->format('M j, Y g:i A') }} + @else + Never used + @endif + + + + +
  • + @endforeach +
+ @else +

You haven't set up any passkeys yet.

+ @endif +
+``` +:: + +## Aliasing + +You can use the `as` parameter to alias the passkeys into a variable, which allows you to use `{{ if passkeys }}` to check if there are any passkeys before rendering. + +```antlers +{{ user:passkeys as="passkeys" }} + {{ if passkeys }} + {{# Render passkeys list #}} + {{ /if }} +{{ /user:passkeys }} +``` From 6feec694ddfd71736428ff4dd7d97825ea1705b4 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Fri, 10 Apr 2026 09:52:57 +0100 Subject: [PATCH 2/2] address pr comments --- content/collections/tags/user-login_form.md | 42 +++++++----------- content/collections/tags/user-passkey_form.md | 44 +++---------------- 2 files changed, 23 insertions(+), 63 deletions(-) diff --git a/content/collections/tags/user-login_form.md b/content/collections/tags/user-login_form.md index 8c02c8202..5a152dba6 100644 --- a/content/collections/tags/user-login_form.md +++ b/content/collections/tags/user-login_form.md @@ -34,10 +34,6 @@ variables: name: success type: string description: A success message. - - - name: passkeys_enabled - type: boolean - description: Whether passkey authentication is configured. - name: passkey_options_url type: string @@ -130,27 +126,23 @@ You can add passkey authentication to your login form using Statamic's frontend - {{ if passkeys_enabled }} {{# [tl! focus:start] #}} - - - - {{ /if }} {{# [tl! focus:end] #}} + {{# [tl! focus:start] #}} + + {{# [tl! focus:end] #}} {{ /user:login_form }} ``` 3. Add `autocomplete="username webauthn"` to your email input for browser autofill to work. diff --git a/content/collections/tags/user-passkey_form.md b/content/collections/tags/user-passkey_form.md index f2fc21969..5f0e8d6db 100644 --- a/content/collections/tags/user-passkey_form.md +++ b/content/collections/tags/user-passkey_form.md @@ -6,21 +6,13 @@ description: 'Creates a passkey registration form' intro: 'Allows authenticated users to set up passkeys' variables: - - name: create_url + name: passkey_option_url type: string description: 'URL to fetch WebAuthn attestation options for creating a new passkey.' - - name: store_url + name: passkey_verify_url type: string description: 'URL to store the new passkey after registration.' - - - name: errors - type: array - description: An array of validation errors. - - - name: success - type: string - description: A success message. related_entries: - 38323438-4719-4a7b-ba5a-8abfe0d7dfc0 - d0ed4ac0-536a-47a1-965b-202b52baddb2 @@ -48,25 +40,13 @@ You'll need to include the frontend helpers script on your page: - {{ if success }} -

Passkey created successfully!

- {{ /if }} - - {{ if errors }} -
    - {{ errors }} -
  • {{ value }}
  • - {{ /errors }} -
- {{ /if }} -