fido2-net-lib is a free, open source identity & access management (iam) project written in C# and released under MIT. It has 1,452 GitHub stars, 202 forks and 20 open issues, and was last pushed 34 hours ago. On this registry it ranks #28 of 30 tracked projects in Identity & Access Management (IAM), with 5 head-to-head comparisons available.

What is fido2-net-lib?

fido2-net-lib is an open-source, MIT-licensed C# library that provides a FIDO2 server and WebAuthn relying party implementation for .NET, aimed at developers who want passkey registration and sign-in in ASP.NET Core, .NET Core and native .NET applications without writing the credential validation logic themselves.

What it is

fido2-net-lib is a .NET library for passkeys, FIDO2 and WebAuthn, distributed as the Fido2 NuGet package and maintained as part of the .NET Foundation. It implements the relying party side of the WebAuthn specification: validating registration ceremonies (attestation) and authentication ceremonies (assertion) for FIDO2 and WebAuthn credentials. The README describes it as fully working and battle tested, with the stated purpose of enabling passwordless sign-in for all .NET apps — ASP.NET, .NET Core and native. It sits in the Security & Privacy / Identity & Access Management category, is written in C#, and carries the topics fido2, webauthn, ctap, passkeys, passwordless, asp-net-core and net-core.

The problem it solves is that verifying a WebAuthn ceremony correctly — parsing authenticator data and checking the challenge, origin, and the attestation and assertion structures the specification defines — is detailed protocol work that most application teams do not want to reimplement. This library replaces that hand-rolled validation code with a tested implementation. It also addresses the gap left by the passkey support that arrived in .NET 10: that support is available only as part of ASP.NET Identity, whereas this library is a more capable implementation and is what Microsoft recommends when attestation or newer passkey features are required.

Key capabilities

  • Validates WebAuthn registration (attestation) and authentication (assertion) ceremonies for FIDO2 and WebAuthn credentials.
  • Attestation support, which the README identifies as beyond what the .NET 10 ASP.NET Identity passkey implementation offers.
  • ASP.NET Core helpers in the separate Fido2.AspNet package.
  • Blazor WebAssembly support in the separate Fido2.BlazorWebAssembly package.
  • Works with FIDO2/CTAP authenticators and passkeys, covering the passwordless sign-in flow.
  • Can be combined with the ASP.NET Identity passkey implementation through the plugin interface Microsoft built, rather than being an all-or-nothing choice.
  • Distributed as the Fido2 NuGet package and tracked with codecov reporting.

Who uses it and how

  • ASP.NET Core applications that need passkey sign-in and want to stay independent of ASP.NET Identity.
  • Single-page applications that perform authentication without the ASP.NET Identity stack, using the library server-side to validate ceremonies.
  • Blazor WebAssembly projects, using Fido2.BlazorWebAssembly.
  • Teams that require attestation, or that want access to newer parts of the evolving passkey standard faster than the ASP.NET Identity implementation provides.
  • Native .NET applications, which the README names alongside ASP.NET and .NET Core as targets.

Getting started

Install with dotnet add package Fido2; the requirement is .NET 8.0 or later. Add Fido2.AspNet for ASP.NET Core helpers or Fido2.BlazorWebAssembly for Blazor WebAssembly support. Teams upgrading from v3.x should follow Documentation/migration-guide-4.0.0.md, which documents the breaking changes.

How it compares

Among the alternatives named in the README, the .NET 10 passkey support is confined to ASP.NET Identity and lacks advanced features such as attestation, while the Bitwarden Passwordless API is a hosted service that is free up to 10,000 users. This library is MIT-licensed and self-hosted, so there is no per-user fee and no third party in the authentication path — the trade-off is that hosting and integration work stays with the adopting team. It also interoperates with the ASP.NET Identity implementation rather than competing with it outright.

When to use it — and when not to

A team adopting this library operates the .NET application around it, but the README describes no storage or database component, so persisting credential records and running the surrounding service remain the adopter's responsibility. It is not the right pick for a team already running the vanilla ASP.NET Identity stack that needs passkeys but no attestation or newer features, since the built-in support is sufficient there. Upgraders from v3.x should also account for the breaking changes documented in the migration guide before moving to v4.

project readme (upstream, from github) — read inline

Passkeys - FIDO2 .NET Library (WebAuthn)

A fully working and battle tested library for passkeys (FIDO2 and WebAuthn) on .NET

codecov Financial Contributors on Open Collective NuGet Status

Releases & Change log

💡 Bitwarden Passwordless API

The quickest way to get started with FIDO2 and WebAuthn is with the Bitwarden Passwordless API. It's free up to 10k users and a faster way to start using passkeys on your website or mobile app.

Bitwarden Passwordless.dev supports .NET Framework as well as the latest .net 8+.

Get started with passwordless.dev

Purpose

Our purpose is to enable passwordless sign in for all .NET apps (asp, core, native).

To provide a developer friendly and well tested .NET FIDO2 Server / WebAuthn relying party library for the easy validation of registration (attestation) and authentication (assertion) of FIDO2 / WebAuthn credentials, in order to increase the adoption of the technology, ultimately defeating phishing attacks.

This project is part of the .NET foundation

.NET 10 Passkeys vs this library?

Wondering if you should use what's in .NET 10 or this library? I've worked together with Microsoft on their passkey implementation and how it relates to this library, so I can share some perspective that may be aid in your decision:

  • The passkey support announced Microsoft in .NET 10 is only available as part of ASP.NET Identity.
  • Fido2-net-lib is a more capable implementation, and Microsoft recommends you to use this (or any other 3p library) if you want to use more advanced features like attestation. They built a plugin interface so you can combine this library with theirs.
  • Since the passkey specification is evolving, I think using this library will give you access to new parts of the standard faster than using ASP.NET Identity.

When picking Microsoft asp.net identity is a good idea:

  • You're using ASP.NET Identity and need passkeys.
  • You don't want to use attestation or newer passkey features

When picking this library is a good idea:

  • You don't want to be tied to using ASP.NET Identity
  • You're building a SPA and doing auth without asp.net identity
  • You want to use modern passkey features
  • You want to use attestation (Could combine this library with the asp.net identity version)

I'm happy that Microsoft is finally joining the passkey train, but this library is probably still what you want to use unless you're running the vanilla asp.net Identity-stack. At least for the time beeing.

Installation

Requirements: .NET 8.0 or later

dotnet add package Fido2

To use the ASP.NET Core helpers:

dotnet add package Fido2.AspNet

For Blazor WebAssembly support:

dotnet add package Fido2.BlazorWebAssembly

⚠️ Breaking Changes: If upgrading from v3.x, see the Upgrade Guide for migration instructions.

Demo

What is FIDO2?

The passwordless web is here. FIDO2 / WebAuthn is a modern, stable and open authentication standard, supported by browsers and many large tech companies such as Microsoft, Google etc. The main driver is to allow a user to login without passwords, creating passwordless flows or strong MFA for user signup/login on websites. The standard is not limited to web applications with support coming to native apps. The technology builds on public/private keys, allowing authentication to happen without sharing a secret between the user & website. This brings many benefits, such as easier and safer logins and makes phishing attempts extremely hard.

Read more:

Supported features

  • ✅ Attestation API & verification (Register and verify credentials/authenticators)
  • ✅ Assertion API & verification (Authenticate users)
  • ✅ 100% pass rate in conformance testing (results)
  • ✅ FIDO2 security keys aka roaming authenticators (spec), like SoloKeys Solo, Yubico YubiKey, and Feitian BioPass FIDO2)
  • ✅ Device embedded authenticators aka platform authenticators (spec), like Android Key and TPM)
  • ✅ Backwards compatibility with FIDO U2F authenticators (spec)
  • Windows Hello
  • Face ID and Touch ID for the Web (aka "Apple Hello")
  • ✅ All currently referenced cryptographic algorithms for FIDO2 Server (spec)
  • ✅ All current attestation formats: "packed", "tpm", "android-key", "android-safetynet", "fido-u2f", "apple", "apple-appattest", and "none" (spec)
  • ✅ FIDO2 Server attestation validation via FIDO Metadata Service V3 (spec)
  • ✅ WebAuthn extensions (spec) including PRF, Large Blob, Credential Protection
  • ✅ Blazor WebAssembly support for client-side applications
  • ✅ Examples & demos (ASP.NET Core and Blazor WebAssembly)
  • ✅ Intellisense documentation

Configuration

Only some options are mentioned here, see the Configuration class for all options

  • fido2:MDSCacheDirPath - App Secret / environment variable that sets the cache path for the MDS. Defaults to "current user's temporary folder"/fido2mdscache. Optional when using the default MetadataService provider.

Quick Start

1. Configure Services (ASP.NET Core)

services.AddFido2(options =>
{
    options.ServerDomain = "example.com";
    options.ServerName = "Example App";
    options.Origins = new HashSet<string> { "https://example.com" };
});

2. Inject IFido2 Service

public class AuthController : Controller
{
    private readonly IFido2 _fido2;

    public AuthController(IFido2 fido2)
    {
        _fido2 = fido2;
    }
}

Examples

For integration patterns, see:

Create Attestation Options

To add FIDO2 credentials to an existing user account, start by creating options for the client.

// 1. Get user from DB by username (in our example, auto create missing users)
var user = DemoStorage.GetOrAddUser(username, () => new User
{
    DisplayName = "Display " + username,
    Name = username,
    Id = Encoding.UTF8.GetBytes(username) // byte representation of userID is required
});

// 2. Get user existing keys by username
var existingKeys = DemoStorage.GetCredentialsByUser(user)
    .Select(c => c.Descriptor)
    .ToList();

// 3. Create options using new parameter wrapper
var options = _fido2.RequestNewCredential(new RequestNewCredentialParams
{
    User = user,
    ExcludeCredentials = existingKeys,
    AuthenticatorSelection = AuthenticatorSelection.Default,
    AttestationPreference = AttestationConveyancePreference.Parse(attType),
    Extensions = new AuthenticationExtensionsClientInputs
    {
        CredProps = true  // Enable credential properties extension
    }
});

// 4. Temporarily store options, session/in-memory cache/redis/db
HttpContext.Session.SetString("fido2.attestationOptions", options.ToJson());

// 5. Return options to client
return Json(options);

Register Credentials

When the client returns a response, verify and register the credentials.

// 1. Get the options we sent the client and remove from storage
var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions");
HttpContext.Session.Remove("fido2.attestationOptions");
var options = CredentialCreateOptions.FromJson(jsonOptions);

// 2. Create callback so that lib can verify credential id is unique to this user
IsCredentialIdUniqueToUserAsyncDelegate callback = async (IsCredentialIdUniqueToUserParams args) =>
{
    var users = await DemoStorage.GetUsersByCredentialIdAsync(args.CredentialId);
    return users.Count == 0; // Return true if credential ID is unique
};

// 3. Verify and make the credentials using new parameter wrapper
var result = await _fido2.MakeNewCredentialAsync(new MakeNewCredentialParams
{
    AttestationResponse = attestationResponse,
    OriginalOptions = options,
    IsCredentialIdUniqueToUserCallback = callback
});

// 4. Store the credentials in database
DemoStorage.AddCredentialToUser(options.User, new StoredCredential
{
    Descriptor = new PublicKeyCredentialDescriptor(result.Id),
    PublicKey = result.PublicKey,
    UserHandle = result.User.Id
});

// 5. Return success to client
return Json(result);

Create Assertion Options

For user authentication, create assertion options based on registered credentials.

// 1. Get user from DB
var user = DemoStorage.GetUser(username);
if (user == null) return NotFound("Username was not registered");

// 2. Get registered credentials from database
var existingCredentials = DemoStorage.GetCredentialsByUser(user)
    .Select(c => c.Descriptor)
    .ToList();

// 3. Create options using new parameter wrapper
var options = _fido2.GetAssertionOptions(new GetAssertionOptionsParams
{
    AllowedCredentials = existingCredentials,
    UserVerification = UserVerificationRequirement.Preferred,
    Extensions = new AuthenticationExtensionsClientInputs
    {
        Extensions = true
    }
});

// 4. Temporarily store options, session/in-memory cache/redis/db
HttpContext.Session.SetString("fido2.assertionOptions", options.ToJson());

// 5. Return options to client
return Json(options);

Verify the Assertion Response

When the client returns a response, verify it and accept the login.

// 1. Get the assertion options we sent the client and remove from storage
var jsonOptions = HttpContext.Session.GetString("fido2.assertionOptions");
HttpContext.Session.Remove("fido2.assertionOptions");
var options = AssertionOptions.FromJson(jsonOptions);

// 2. Get registered credential from database
var creds = DemoStorage.GetCredentialById(clientResponse.Id);

// 3. Create callback to check if userhandle owns the credentialId
IsUserHandleOwnerOfCredentialIdAsync callback = async (args) =>
{
    var storedCreds = await DemoStorage.GetCredentialsByUserHandleAsync(args.UserHandle);
    return storedCreds.Exists(c => c.Descriptor.Id.SequenceEqual(args.CredentialId));
};

// 4. Make the assertion using new parameter wrapper
var result = await _fido2.MakeAssertionAsync(new MakeAssertionParams
{
    AssertionResponse = clientResponse,
    OriginalOptions = options,
    StoredPublicKey = creds.PublicKey,
    StoredSignatureCounter = creds.SignatureCounter,
    IsUserHandleOwnerOfCredentialIdCallback = callback
});

// 5. Store the updated counter
DemoStorage.UpdateCounter(result.CredentialId, result.Counter);

// 6. Return success to client
return Json(result);

Nuget package

https://www.nuget.org/packages/Fido2/ and https://www.nuget.org/packages/Fido2.Models/

Contributing

See Contributing for information about contributing to the project.

This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the .NET Foundation Code of Conduct.

For security and penetration testing, please see our Vulnerability Disclosure Program

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

.NET Foundation

This project is supported by the .NET Foundation.

Frequently asked questions

Is fido2-net-lib free to use?

fido2-net-lib is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does fido2-net-lib do?

Passkeys, FIDO2 and WebAuthn .NET library.

What is fido2-net-lib written in?

fido2-net-lib is primarily written in C#. Its source is publicly available at https://github.com/passwordless-lib/fido2-net-lib, and it has 1,452 GitHub stars.