2020-10-20 01:13:09 +02:00
2020-10-20 01:13:09 +02:00
2020-10-19 21:17:54 +02:00
2020-10-19 21:17:54 +02:00
2020-10-19 21:17:54 +02:00
2020-10-19 21:17:54 +02:00
2020-10-20 01:13:09 +02:00
2020-10-20 01:13:09 +02:00
2020-10-19 21:17:54 +02:00
2020-10-19 21:17:54 +02:00

WebAuthn Interop Assembly

MIT License Windows 10 1903+ .NET Framework 4.7+ .NET Core 3+

FIDO2 / W3C Web Authentication .NET Library for Windows Desktop and CLI Applications

Introduction

This library allows .NET applications to directly interact with FIDO2 security keys (e.g. YubiKey, Feitian, or Crayonic) and with Windows Hello / Windows Hello for Business. It provides a managed wrapper of the low-level Windows 10 WebAuthn API (exposed through the webauthn.dll system library). This API is mainly used by browsers (see the source code of Chromium and Firefox) to implement passwordless web authentication, but it can also be used by any .NET desktop or CLI application.

As a front-end, this library uses classes defined in the Fido2.Models package, which it then translates to native C structures. See the project site for more details.

Downloads

The DSInternals.Win32.WebAuthn library is published in the NuGet Gallery.

Usage

Overview

The WebAuthn API is only supported on Windows 10 1903 and newer. It is exposed in the DSInternals.Win32.WebAuthn namespace, with the WebAuthnApi class being the main entry point.

Following are code samples that mimic the behavior of login.microsoftonline.com. The samples are not ready for production use, as they are missing validation and contain many hardcoded values. Especially the challenge must be randomly generated in a cryptographically safe way.

Registration (Attestation)

Credential registration is performed by calling the AuthenticatorMakeCredential or AuthenticatorMakeCredentialAsync method:

var config = new Fido2Configuration()
{
    Origin = "login.microsoft.com",
    ServerDomain = "login.microsoft.com",
    ServerName = "Microsoft"
};

var user = new Fido2User
{
    Name = "john.doe@outlook.com",
    DisplayName = "John Doe",
    Id = Base64Url.Decode("TUY65dH-Otl4jMdTRvlFQ1aApACYsuqGKSPQDQc1Bd4WVyw")
};

var authenticator = new AuthenticatorSelection
{
    AuthenticatorAttachment = Fido2NetLib.Objects.AuthenticatorAttachment.CrossPlatform,
    RequireResidentKey = true,
    UserVerification = Fido2NetLib.Objects.UserVerificationRequirement.Required,
};

byte[] challenge = Encoding.ASCII.GetBytes("CbWTU93Ppbgok1glyka*K9sZSWkqpK3qS1ldeLJxsI4k3jMLIi3dl8VDx10siTGd8U5SNj8yyMIbqXQH!apXGnrhWmYlg2GNdEGddIkO03cql!kKVgKi*MqEIl9aPqmJdYuRMjrEYlIyzi4*wP0YSyA$");

var excludedCredentials = new List<PublicKeyCredentialDescriptor>()
{
    new PublicKeyCredentialDescriptor(Base64Url.Decode("lz6_hw1jzaRNhhu9dt_M1Q=")),
    new PublicKeyCredentialDescriptor(Base64Url.Decode("Zod6YhgNV2dQeT3v8ekjRpU0nVlEkPlpXF5Vx6f4P9g=")),
    new PublicKeyCredentialDescriptor(Base64Url.Decode("sx2P4XkPO6TUoSf0pMEm3zi5gdwVrIRjiYvuTFRAkNMe_jVsntSgkyG5aV8er5GCA_G1X2idph-8lhhMFX3aaAyBCQIAAA="))
};

var options = CredentialCreateOptions.Create(
    config,
    challenge,
    user,
    authenticator,
    Fido2NetLib.Objects.AttestationConveyancePreference.Direct,
    excludedCredentials,
    null
);

options.PubKeyCredParams = new List<PubKeyCredParam>()
{
    new PubKeyCredParam() { Alg = -7, Type = PublicKeyCredentialType.PublicKey },
    new PubKeyCredParam() { Alg = -257, Type = PublicKeyCredentialType.PublicKey }
};

var webauthn = new WebAuthnApi();
var response = webauthn.AuthenticatorMakeCredential(options);

Authentication (Assertion)

Authentication using a previously registered credential is performed by calling the AuthenticatorGetAssertion or AuthenticatorGetAssertionAsync method:

var config = new Fido2Configuration()
{
    Origin = "login.microsoft.com",
    ServerDomain = "login.microsoft.com",
    ServerName = "Microsoft"
};

byte[] challenge = Encoding.ASCII.GetBytes("O.eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImtnMkxZczJUMENUaklmajRydDZKSXluZW4zOCJ9.eyJhdWQiOiJ1cm46bWljcm9zb2Z0OmZpZG86Y2hhbGxlbmdlIiwiaXNzIjoiaHR0cHM6Ly9sb2dpbi5taWNyb3NvZnQuY29tIiwiaWF0IjoxNjAyNDEzMzIxLCJuYmYiOjE2MDI0MTMzMjEsImV4cCI6MTYwMjQxMzYyMX0.ogwFJG0w6TX4QAGmwh-0aizApfdxtpQ_Kra9Bjk7LCuHxglV1rU1C5U9nPx4cKoNh09zucnTx9HpbvytgQtenOHiErZswGY_oi53EGL_ftfICm80agFcwMYLzHPH-yoIE9B5uORnLFOZmz98aZAFXcofZcK1E3-A1wZVcES9mjBN34G6iwG7-pcmBJge0Xc8nkRO-dei4RlFWnnYNc6iSPuJEknojGAvstmkfqSGnNgTpQXvn5eBVSHltY1C8jkk-qUzNxf1mfypcdXxfZxAIQnc50JRDz1QsD6bKV97crqhvv1ROpQ3L1V6dtYYiIQAUKQgm6FhYbS-3uj3ziK_fA");

var allowedCredentials = new List<PublicKeyCredentialDescriptor>()
{
    new PublicKeyCredentialDescriptor(Base64Url.Decode("sx2P4XkPO6TUoSf0pMEm3zi5gdwVrIRjiYvuTFRAkNMe_jVsntSgkyG5aV8er5GCA_G1X2idph-8lhhMFX3aaAyBCQIAAA")),
    new PublicKeyCredentialDescriptor(Base64Url.Decode("JmLEadmzHpm5K3i5gVFO-MJz43GukTKYkcRR8qO6Bp0")),
    new PublicKeyCredentialDescriptor(Base64Url.Decode("lz6_hw1jzaRNhhu9dt_M1Q"))
};

var options = AssertionOptions.Create(
    config,
    challenge,
    allowedCredentials,
    Fido2NetLib.Objects.UserVerificationRequirement.Required,
    null
);
           
var webauthn = new WebAuthnApi();
var response = webauthn.AuthenticatorGetAssertion(options);

See the full API documentation for more information about using this library.

Code Generation

The APiConstants.cs file is automatically generated from #define statements in webauthn.h. This is performed in the DSInternals.Win32.WebAuthn.CodeGen helper application by leveraging the CppAst.NET project.

Microsoft's Documentation

Acknowledgements

S
Description
Automated archival mirror of github.com/MichaelGrafnetter/webauthn-interop
Readme MIT
4.5 MiB
Languages
C# 89.1%
PowerShell 10.9%