This repository provides a server-side implementation of the WebAuthn standard, enabling secure passwordless and multi-factor authentication (MFA) for web applications. It supports key WebAuthn operations – credential registration and authentication – ensuring compliance with the WebAuthn Level 2 specification (Web Authentication: An API for accessing Public Key Credentials Level 2).
- Attestation flow for public key credential registration
- Assertion flow for public key credential verification
- Supported attestation statement formats:
- Packed
- TPM
- Android Key
- Android SafetyNet
- FIDO U2F
- None
- Apple Anonymous
- Supported cryptographic algorithms: ES256, EdDSA, ES384, ES512, PS256, PS384, PS512, ES256K, RS256, RS384, RS512, RS1
- Built-in storage providers:
- Microsoft SQL Server
- PostgreSQL
- Amazon DynamoDB
- In-memory storage
- FIDO Metadata Service
- Fully tested with the FIDO Conformance Tool – all test cases successfully passed
- Code samples and demo website
| Package Name | Status |
|---|---|
| Shark.Fido2.Core | |
| Shark.Fido2.DynamoDB | |
| Shark.Fido2.InMemory | |
| Shark.Fido2.Models | |
| Shark.Fido2.PostgreSQL | |
| Shark.Fido2.SqlServer |
ASP.NET Core Identity includes built-in support for passkeys starting in .NET 10.
| Capability | Shark WebAuthn | ASP.NET Core Identity |
|---|---|---|
| Library Scope | General-purpose WebAuthn library, not tied to ASP.NET Core Identity | Integrated with ASP.NET Core Identity; not a general WebAuthn library and primarily scoped to Identity use cases |
| .NET Version | Targets .NET 8 (compatible with .NET 8/9/10) | Requires .NET 10 SDK |
| Developer Experience | Available as NuGet packages | Built into .NET 10, no package to install |
| Attestation Support | Comprehensive support for all attestation formats | ❌ No default attestation validation |
| Cryptographic Algorithms | Supports all WebAuthn-defined cryptographic algorithms | Supports all WebAuthn-defined cryptographic algorithms except EdDSA. Source |
| Persistent Data Stores | Provides built-in providers for Microsoft SQL Server, PostgreSQL, Amazon DynamoDB, and in-memory storage | Uses ASP.NET Core Identity's configured storage providers |
| FIDO Metadata Service | Built-in integration with the FIDO Metadata Service | ❌ No built-in integration with the FIDO Metadata Service |
| FIDO Conformance Tool | Tested | Tested |
Choose Shark WebAuthn when:
- You need full, standards-compliant WebAuthn support
- You need flexibility in choosing the persistent data store
- You are building with enterprise or regulatory compliance requirements in mind
- You require additional authenticator validation via the FIDO Metadata Service
Choose Passkeys in ASP.NET Core Identity when:
- You are already using ASP.NET Core Identity in your application
- You only need basic passkey-based, passwordless authentication
- You are willing to implement custom attestation validation if needed
The following examples demonstrate how to implement passwordless authentication in your application. For complete reference and additional details, see the full documentation.
The sample C# code below is designed for ASP.NET Core controllers.
Registers both the credential store (in-memory or alternative) and the core dependencies.
builder.Services.AddFido2(builder.Configuration);
builder.Services.AddFido2InMemoryStore();The server side can be customized using the following configuration options. You can set these options in an appsettings.json file.
Core Configuration
| Option | Default | Description |
|---|---|---|
RelyingPartyId |
Valid domain string identifying the Relying Party on whose behalf a given registration or authentication ceremony is being performed. This is a critical parameter in the WebAuthn protocol. It defines the security scope within which credentials are valid. Therefore, careful selection is essential, as an incorrect or overly broad value can lead to unintended credential reuse or security vulnerabilities. | |
RelyingPartyIdName |
Human-readable identifier for the Relying Party, intended only for display. | |
Origins |
List of the fully qualified origins of the Relying Party making the request, passed to the authenticator by the browser. | |
Timeout |
60000 |
Time, in milliseconds, that the Relying Party is willing to wait for the call to complete. |
AlgorithmsSet |
Extended |
Set of the supported cryptographic algorithms. Possible values are Required, Recommended or Extended. More information about the cryptographic algorithms is available on the fidoalliance.org site. |
AllowNoneAttestation |
true |
Value indicating whether None attestation type is acceptable under Relying Party policy. None attestation is used when the authenticator doesn't have any attestation information available. |
AllowSelfAttestation |
true |
Value indicating whether Self attestation type is acceptable under Relying Party policy. Self attestation is used when the authenticator doesn't have a dedicated attestation key pair or a vendor-issued certificate. |
EnableTrustedExecutionEnvironmentOnly |
true |
Value indicating whether the Relying Party trusts only keys that are securely generated and stored in a Trusted Execution Environment (relevant for Android Key Attestation). |
EnableMetadataService |
true |
Value indicating whether the Relying Party uses the FIDO Metadata Service to verify the attestation object. Metadata from the FIDO Metadata Service is stored in an in-memory cache and remains valid until the nextUpdate timestamp, which is received from the metadata BLOB and indicates the latest time a new metadata BLOB may be provided. |
EnableStrictAuthenticatorVerification |
false |
Value indicating whether the Relying Party requires strict verification of authenticators. If enabled, missing metadata for the authenticator would cause attestation to fail. This parameter is ignored if the FIDO Metadata Service is disabled. |
FIDO Metadata Service Configuration
| Option | Default | Description |
|---|---|---|
MetadataBlobLocation |
https://mds3.fidoalliance.org/ |
Location of the centralized and trusted source of information about FIDO authenticators (Metadata Service BLOB). |
RootCertificateLocationUrl |
https://secure.globalsign.com/cacert/root-r3.crt |
Location of GlobalSign Root R3 certificate for Metadata Service BLOB. |
MaximumTokenSizeInBytes |
8388608 |
Maximum token size in bytes that will be processed. This configuration is related to the Metadata Service BLOB size. |
Example appsettings.json file: appsettings.Production.json
Attestation controller
- Begin registration by retrieving create options.
[HttpPost("options")]
public async Task<IActionResult> Options(ServerPublicKeyCredentialCreationOptionsRequest request, CancellationToken cancellationToken)
{
var createOptions = await _attestation.BeginRegistration(request.Map(), cancellationToken);
var response = createOptions.Map();
HttpContext.Session.SetString("CreateOptions", JsonSerializer.Serialize(createOptions));
return Ok(response);
}- Complete registration to create credential.
[HttpPost("result")]
public async Task<IActionResult> Result(ServerPublicKeyCredentialAttestation request, CancellationToken cancellationToken)
{
var createOptionsString = HttpContext.Session.GetString("CreateOptions");
var createOptions = JsonSerializer.Deserialize<PublicKeyCredentialCreationOptions>(createOptionsString!);
await _attestation.CompleteRegistration(request.Map(), createOptions!, cancellationToken);
return Ok(ServerResponse.Create());
}Assertion controller
- Begin authentication by retrieving request options.
[HttpPost("options")]
public async Task<IActionResult> Options(ServerPublicKeyCredentialGetOptionsRequest request, CancellationToken cancellationToken)
{
var requestOptions = await _assertion.BeginAuthentication(request.Map(), cancellationToken);
var response = requestOptions.Map();
HttpContext.Session.SetString("RequestOptions", JsonSerializer.Serialize(requestOptions));
return Ok(response);
}- Complete authentication to validate credential.
[HttpPost("result")]
public async Task<IActionResult> Result(ServerPublicKeyCredentialAssertion request, CancellationToken cancellationToken)
{
var requestOptionsString = HttpContext.Session.GetString("RequestOptions");
var requestOptions = JsonSerializer.Deserialize<PublicKeyCredentialRequestOptions>(requestOptionsString!);
await _assertion.CompleteAuthentication(request.Map(), requestOptions!, cancellationToken);
return Ok(ServerResponse.Create());
}To finalize the implementation, you must incorporate JavaScript code that interacts with the browser's Web Authentication API. This API manages the client-side authentication process. The following is a sample implementation:
- attestation.js handles the registration process using the Web Authentication API (
navigator.credentials.create). - assertion.js handles the authentication process using the Web Authentication API (
navigator.credentials.get).
This JavaScript code binds the browser's Web Authentication API to the server-side REST API endpoints provided by the ASP.NET Core controllers described above. More information about the Web Authentication API is available on the MDN Web Docs site at developer.mozilla.org page.
The sample relying party can be run using Docker (Linux container). Make sure Docker is installed and running on your machine.
Pull and Run the Image
docker pull linuxchata/shark-fido2-sample:latestdocker run -d -e ASPNETCORE_ENVIRONMENT=Development -p 8080:8080 linuxchata/shark-fido2-sample:latestThe application will be accessible at http://localhost:8080.
All test cases successfully passed using the official FIDO Conformance Tool, confirming full compliance with the WebAuthn Level 2 and FIDO2 specifications.
This project is licensed under the BSD 3-Clause License.
See Contributing for information about contributing to the project.
Introduction
Web Authentication
- Web Authentication: An API for accessing Public Key Credentials Level 2
- Server Requirements and Transport Binding Profile
- Web Authentication: An API for accessing Public Key Credentials Level 3
- PublicKeyCredential
FIDO Metadata Service
Tools