> For the complete documentation index, see [llms.txt](https://webauthn-doc.spomky-labs.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://webauthn-doc.spomky-labs.com/v5.2/symfony-ux/installation.md).

# Installation

The [Symfony UX Initiative](https://symfony.com/ux) enables high-interaction applications directly from Twig templates without writing custom JavaScript. The WebAuthn Stimulus Controller makes implementing passwordless authentication as simple as adding a few Twig functions to your forms.

## Prerequisites

Before installing the Stimulus Controller, you need:

1. **Symfony UX configured** - Follow the [official Symfony UX documentation](https://symfony.com/doc/current/frontend/ux.html)
2. **WebAuthn Bundle installed** - See [Symfony Bundle Installation](https://github.com/web-auth/doc/blob/5.2/symfony-ux/the-symfony-way.md)

## Installation

Install the WebAuthn Stimulus Controller via Composer:

```bash
composer require web-auth/webauthn-stimulus
```

This command will automatically:

* Install the PHP package
* Register the Stimulus controller via Symfony Flex
* Configure AssetMapper to import the necessary JavaScript files

{% hint style="info" %}
**No build step required!** The package works with Symfony AssetMapper, so you don't need Node.js, npm, yarn, or any JavaScript build tools. The browser imports the JavaScript files directly.
{% endhint %}

## Verify Installation

Check that the Stimulus controller is properly registered in your `assets/controllers.json`:

{% code title="assets/controllers.json" lineNumbers="true" %}

```json
{
    "controllers": {
        "@web-auth/webauthn-stimulus": {
            "enabled": true
        }
    }
}
```

{% endcode %}

## What's Included

The package provides a Stimulus controller that handles:

* **Registration flows** - Calls `navigator.credentials.create()` for you
* **Authentication flows** - Calls `navigator.credentials.get()` for you
* **Base64 encoding/decoding** - Automatically handles data conversion
* **Error handling** - Gracefully handles common WebAuthn errors
* **Browser autofill** - Supports conditional UI for passkey selection

## Basic Usage

Once installed, you can use the Stimulus controller in your Twig templates with two simple functions:

1. **`stimulus_controller()`** - Attach the controller to your form
2. **`stimulus_action()`** - Trigger WebAuthn operations on button clicks

### Registration Form Example

{% code title="templates/registration/register.html.twig" lineNumbers="true" %}

```twig
<form
    action="{{ path('app_register') }}"
    method="post"
    {{ stimulus_controller('@web-auth/webauthn-stimulus', {
        creationOptionsUrl: path('webauthn.controller.creation.request.new_user'),
        creationResultField: 'input[name="attestation"]'
    }) }}
>
    <input type="text" name="username" required>
    <input type="hidden" name="attestation">

    <button
        type="submit"
        {{ stimulus_action('@web-auth/webauthn-stimulus', 'signup') }}
    >
        Register
    </button>
</form>
```

{% endcode %}

### Authentication Form Example

{% code title="templates/security/login.html.twig" lineNumbers="true" %}

```twig
<form
    action="{{ path('app_login') }}"
    method="post"
    {{ stimulus_controller('@web-auth/webauthn-stimulus', {
        requestOptionsUrl: path('webauthn.controller.request.request.login'),
        requestResultField: 'input[name="assertion"]'
    }) }}
>
    <input type="text" name="username" autocomplete="username webauthn">
    <input type="hidden" name="assertion">

    <button
        type="submit"
        {{ stimulus_action('@web-auth/webauthn-stimulus', 'signin') }}
    >
        Sign In
    </button>
</form>
```

{% endcode %}

## Controller Options

The Stimulus controller accepts various configuration options:

### Registration Options

| Option                | Type   | Required | Description                                                    |
| --------------------- | ------ | -------- | -------------------------------------------------------------- |
| `creationOptionsUrl`  | string | Yes      | URL endpoint that returns `PublicKeyCredentialCreationOptions` |
| `creationResultField` | string | Yes      | CSS selector for hidden field to store attestation response    |

### Authentication Options

| Option               | Type    | Required | Description                                                   |
| -------------------- | ------- | -------- | ------------------------------------------------------------- |
| `requestOptionsUrl`  | string  | Yes      | URL endpoint that returns `PublicKeyCredentialRequestOptions` |
| `requestResultField` | string  | Yes      | CSS selector for hidden field to store assertion response     |
| `useBrowserAutofill` | boolean | No       | Enable conditional UI for browser autofill (default: false)   |

## Testing Your Installation

Create a simple test page to verify everything works:

{% code title="templates/test/webauthn.html.twig" lineNumbers="true" %}

```twig
{% extends 'base.html.twig' %}

{% block body %}
    <h1>WebAuthn Test</h1>

    {% if app.user %}
        <p>Logged in as: {{ app.user.userIdentifier }}</p>
        <a href="{{ path('app_logout') }}">Logout</a>
    {% else %}
        <h2>Register</h2>
        <form
            action="{{ path('app_register') }}"
            method="post"
            {{ stimulus_controller('@web-auth/webauthn-stimulus', {
                creationOptionsUrl: path('webauthn.controller.creation.request.new_user'),
                creationResultField: 'input[name="attestation"]'
            }) }}
        >
            <label>
                Username:
                <input type="text" name="username" required>
            </label>
            <input type="hidden" name="attestation">

            <button
                type="submit"
                {{ stimulus_action('@web-auth/webauthn-stimulus', 'signup') }}
            >
                Register with WebAuthn
            </button>
        </form>

        <h2>Login</h2>
        <form
            action="{{ path('app_login') }}"
            method="post"
            {{ stimulus_controller('@web-auth/webauthn-stimulus', {
                requestOptionsUrl: path('webauthn.controller.request.request.login'),
                requestResultField: 'input[name="assertion"]'
            }) }}
        >
            <label>
                Username:
                <input type="text" name="username" autocomplete="username webauthn">
            </label>
            <input type="hidden" name="assertion">

            <button
                type="submit"
                {{ stimulus_action('@web-auth/webauthn-stimulus', 'signin') }}
            >
                Sign In with WebAuthn
            </button>
        </form>
    {% endif %}
{% endblock %}
```

{% endcode %}

## Troubleshooting

### Controller Not Found

If you see "Controller '@web-auth/webauthn-stimulus' not found":

1. Verify `assets/controllers.json` includes the controller with `"enabled": true`
2. Clear Symfony cache: `php bin/console cache:clear`
3. Check that AssetMapper is properly configured in `config/packages/asset_mapper.yaml`

### JavaScript Errors

If you see console errors:

1. Ensure you're using **HTTPS** (required for WebAuthn)
2. Check browser console for specific error messages
3. Verify WebAuthn routes are properly configured in `config/routes/webauthn.yaml`
4. Ensure the controller is loaded by checking the browser's network tab

### Assets Not Loading

If the Stimulus controller doesn't load:

1. Verify your base template includes the AssetMapper importmap:

   ```twig
   {% block javascripts %}
       {{ importmap('app') }}
   {% endblock %}
   ```
2. Check that Stimulus is properly configured in your application

## HTTPS Requirement

WebAuthn **requires HTTPS** to function. For development, use the Symfony CLI for automatic HTTPS:

```bash
symfony server:ca:install
symfony serve
```

For production, ensure HTTPS is properly configured on your web server.

## Next Steps

Now that the Stimulus Controller is installed, proceed to:

1. [**User Registration**](/v5.2/symfony-ux/user-registration.md) - Create registration forms
2. [**User Authentication**](/v5.2/symfony-ux/integration.md) - Implement login flows
3. [**Additional Authenticators**](/v5.2/symfony-ux/additional-authenticators.md) - Allow users to register backup devices

## See Also

* [Symfony UX Documentation](https://symfony.com/doc/current/frontend/ux.html) - Official UX guide
* [Stimulus Documentation](https://stimulus.hotwired.dev/) - Stimulus framework reference
* [WebAuthn Bundle](https://github.com/web-auth/doc/blob/5.2/symfony-ux/the-symfony-way.md) - Backend configuration
* [JavaScript Integration](/v5.2/prerequisites/javascript.md) - Manual JavaScript implementation


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://webauthn-doc.spomky-labs.com/v5.2/symfony-ux/installation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
