> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Security key

> Use the Web SDK to enroll and verify hardware security keys.

<Info>
  All Web SDK methods for security keys require you to [initiate an action
  first](/sdks/client/web/actions).
</Info>

Security keys are roaming hardware authenticators (such as YubiKeys) that authenticate using the WebAuthn standard. Unlike passkeys, they are not synced across devices.

## Enroll

Start enrollment for a new security key by prompting the user to register their hardware authenticator.

```ts theme={null}
const response = await authsignal.securityKey.enroll();
```

### Parameters

<ResponseField name="hints" type="string[]">
  An array of [WebAuthn credential hints](https://www.w3.org/TR/webauthn-3/#enum-hints) which guide
  the browser's UI, e.g. `["security-key"]`.
</ResponseField>

### Response

<ResponseField name="response" type="AuthsignalResponse<EnrollResponse>">
  <Expandable title="properties">
    <ResponseField name="data" type="EnrollResponse">
      <Expandable title="properties">
        <ResponseField name="token" type="string">
          A new token which can be used to [validate the
          challenge](/sdks/server/challenges#validate-challenge) on your server.
        </ResponseField>

        <ResponseField name="registrationResponse" type="RegistrationResponseJSON">
          The raw WebAuthn registration response returned by the browser. Most apps can ignore this.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="errorCode" type="string">
      See the [Error handling](/sdks/client/web/error-handling) section for more details.
    </ResponseField>

    <ResponseField name="errorDescription" type="string" />
  </Expandable>
</ResponseField>

## Verify

Re-authenticate an existing security key by prompting the user to present their hardware authenticator.

```ts theme={null}
const response = await authsignal.securityKey.verify();

if (response.data?.token) {
  // Send the response token to your server to validate the result of the challenge
}
```

### Response

<ResponseField name="response" type="AuthsignalResponse<VerifyResponse>">
  <Expandable title="properties">
    <ResponseField name="data" type="VerifyResponse">
      <Expandable title="properties">
        <ResponseField name="isVerified" type="boolean" required>
          True if the verification was successful.
        </ResponseField>

        <ResponseField name="token" type="string">
          A token which can be used for [server-side
          validation](/sdks/server/challenges#validate-challenge).
        </ResponseField>

        <ResponseField name="authenticationResponse" type="AuthenticationResponseJSON">
          The raw WebAuthn authentication response returned by the browser. Most apps can ignore this.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="errorCode" type="string">
      See the [Error handling](/sdks/client/web/error-handling) section for more details.
    </ResponseField>

    <ResponseField name="errorDescription" type="string" />
  </Expandable>
</ResponseField>

## Security key error handling

When any of the underlying native browser WebAuthn APIs fail, the SDK will throw a `WebAuthnError`. Most of these errors are benign and can be safely ignored, for example when the user cancels the ceremony. If you wish to handle them, catch the error in a `try/catch` block. See [Passkey error handling](/sdks/client/web/passkeys#passkey-error-handling) for the common error codes.
