---
source_url: "https://docs.identityserver.com/fido2/webauthn/attestation/"
title: "Attestation | FIDO2 for ASP.NET"
mirrored_at: 2026-08-05T01:04:02.291Z
host: docs.identityserver.com
cited_in_42a: true
mirror_canonical: "https://index.42a.ai/docs.identityserver.com/fido2/webauthn/attestation/index"
---

> **Original source:** https://docs.identityserver.com/fido2/webauthn/attestation/

WebAuthn specifies an API for creating and using public key credentials. Credentials belong to a user and are managed by an authenticator. The process of creating credentials is called attestation. Through Attestation the device can be verified as authentic using trust chains. A successful attestation proves that the device the user has authenticated with is authentic and hasn't been tampered with. From a high level end users perspective, you can think of attestation as a kin to registration.

## Registration

On user action, such as a button click (browsers may block automatic attestation), the Relying Party can request the client to create a new credential, this is done via interaction with the WebAuthn API by calling the `navigator.credentials.create()` method. There are a few different credential options objects we can pass into the function.

-   PublicKeyCredential
-   PasswordCredential
-   FederatedCredential
-   IdentityCredential
-   OTPCredential

For FIDO however the only credential type required is `PublicKeyCredential`.

With the FIDO component the `FidoAuthentication` service can be injected into the controller and the `InitiateRegistration` called before the page load to supply some of the fields required in the options.

### Public Key Credential Options

-   **Attestation** : `string` `Optional` Intended for use by Relying Parties that wish to express their preference for attestation conveyance. Attestation value can either be `direct`, `indirect` or `none`. If no value is provided it will default to `none`.
    
    -   `direct` attestation means the RelyingParty wants to receive the attestation statement as generated by the authenticator. `direct` is the **recommended value**.
    -   `indirect` attestation indicates that the RelyingParty prefers a verifiable attestation statement but allows the client to device how to obtain it.
    -   `none` This means that the relying party is not interested in authenticator attestation.
-   **AuthenticatorSelection** : `object` `Optional` Authenticator requirements object.
    
    -   **AuthenticatorAttachment** : `string`
        -   `platform` indicates a platform authenticator such as WindowsHello or Apple TouchId/FaceId.
        -   `cross-platform` indicates a roaming authenticator such as a security key.
    -   **RequireResidentKey** : `bool` When `true` the authenticator must create a discoverable credential (residence key) for username-less authentication. Not all keys support residence keys.
    -   **UserVerification** : `string` The user verification value can be set as `preferred`, `required` or `discouraged`. If no value is supplied it will default to `preferred`.
        -   `discouraged` means the RelyingParty does not want user verification during the operation, this could be to minimize disruption to the user flow.
        -   `preferred` means that the RelyingParty prefers user verification if possible but will not fail the if the response does have the AuthenticatorDataFlags.UV set.
        -   `required` means the operation will fail if the response does have the AuthenticatorDataFlags.UV set. **The operation will fail if the key does not support user verification and may fail depending on the browser if no PIN or biometric has been configured**
-   **Challenge** : `Uint8Array` A randomly generated value generated by the RelyingParty. In the FIDO2 component the challenge value is generated when calling `FidoAuthentication` `InitiateRegistration` method.
    
-   **ExcludeCredentials** : `Array` Limits creation of multiple credentials for the same account on a single authenticator. If the authenticator finds an existing credential type and id for the RP, then a new credential will not be created. The `FidoAuthentication` `InitiateRegistration` will supply this a list of all credential ids for the user you can use for this option.
    
-   **PubKeyCredParams** Specifies which cryptographic algorithms the RelyingParty supports. The FIDO2 component supports the following algorithms
    
    -   `EdDSA` (Ed25519)
    -   `ES256`
    -   `ES256K`
    -   `ES384`
    -   `ES512`
    -   `PS256`
    -   `PS384`
    -   `PS512`
    -   `RS1`
    -   `RS256`
    -   `RS384`
    -   `RS512`
-   **rp** : `object` Relying party information.
    
    -   `id` The id attribute must equal the domain of the origin seen by the client, or the origin must be a subdomain of the id. If id is omitted, then origins effective domain is used.
    -   `name` Display name, required.
-   **timeout** : `int` The time, in milliseconds, that the caller is willing to wait for the call to complete.
    
-   **user** : `object` Information about the user account.
    
    -   `id` The id attribute is the user handle that is generated by the RP and used to uniquely identify a user. Unlike name, id is not meant to be human-readable and should not contain personally identifying information such as an e-mail address  
        The `FidoAuthentication` `InitiateAuthentication` method will generate a user handle to be used here.
    -   `name` : `string` Username
    -   `displayName` : `string` User-friendly Display name.

## Complete Registration

Once WebAuthn has completed its authentication, the authentication data needs to be passed to the FIDO component to perform attestation and validation. The encoded credentials can be turned into JSON and posted to RegisterCallback endpoint via a javascript promise.

```
    navigator.credentials.create({ publicKey }).then((credentials) => {
        var encodedCredentials = {
            id: credentials.id,
            rawId: btoa(String.fromCharCode.apply(null, new Uint8Array(credentials.rawId))),
            type: credentials.type,
            response: {
                attestationObject:
                    btoa(String.fromCharCode.apply(null, new Uint8Array(credentials.response.attestationObject))),
                clientDataJSON:
                    btoa(String.fromCharCode.apply(null, new Uint8Array(credentials.response.clientDataJSON)))
            }
        };

        $.ajax({
            url: '/Home/RegisterCallback',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify(encodedCredentials),
            success:function() {
                window.location.href = "/";
            }
        });
    });
```

The FIDO component contains types to model FIDO payloads. To receive the encoded credential object from the browser use `Base64FidoRegistrationResponse`. (See code fragment below)

```

    [HttpPost]
    public async Task<IActionResult> RegisterCallback([FromBody] Base64FidoRegistrationResponse registrationResponse)
    {
        IFidoRegistrationResult result = await fido.CompleteRegistration(registrationResponse.ToFidoResponse());

        if (result.IsError) return BadRequest(result.ErrorDescription);
        return Ok();
    }
```

The `FidoAuthentication.CompleteRegistration` method requires a `IFidoRegistrationResponse`, the `ToFidoResponse` extension method generates a `IFidoRegistrationResponse` from the `Base64FidoRegistrationResponse`.

Copyright © 2021 [Rock Solid Knowledge](https://www.rocksolidknowledge.com/) Last updated Thursday 16 July 2026