Node/Deno CI Code Coverage Known Vulnerabilities npm version

Install

Node

npm install fido2-lib --save

Deno

Import dist/main.js from a trusted source. Below is only an example, using jsdelivr.

import { Fido2Lib } from "https://cdn.jsdelivr.net/npm/fido2-lib@latest/dist/main.js";

It is highly recommended that you read this guide to make sure your dependencies, including fido2-lib, are integrity checked.

A short example on how to generate a lock file in Deno 1.x

# Write lock.json using your dependency file as input, re-run when updating dependencies
# Make sure that your dependencies are hosted on sources you trust
deno cache --lock=lock.json --lock-write src/deps.ts

# Then, when running your application, include --lock=lock.json. This will integrity check
# all files included in lock.json
deno run --lock=lock.json --cached-only mod.ts

Overview

A library for performing FIDO 2.0 / WebAuthn server functionality

This library contains all the functionality necessary for implementing a full FIDO2 / WebAuthn server. It intentionally does not implement any kind of networking protocol (e.g. - REST endpoints) so that it can remain independent of any messaging protocols.

There are four primary functions:

  1. attestationOptions - creates the challenge that will be sent to the client (e.g. - browser) for the credential create call. Note that the library does not keep track of sessions or context, so the caller is expected to associate the resulting challenge with a session so that it can be appropriately matched with a response.
  2. attestationResult - parses and validates the response from the client
  3. assertionOptions - creates the challenge that will be sent to the client for credential assertion.
  4. assertionResult - parses and validates the response from the client

There is also an extension point for adding new attestation formats.

Full documentation can be found here.

For working examples see OWASP Single Sign-On and / or webauthn.io

Features

  • Works with Windows Hello
  • Attestation formats: packed, tpm, android-safetynet, fido-u2f, none
  • Convenient API for adding more attestation formats
  • Convenient API for adding extensions
  • Metadata service (MDS) support enables authenticator root of trust and authenticator metadata
  • Support for multiple simultaneous metadata services (e.g. FIDO MDS 1 & 2)
  • Crypto families: ECDSA, RSA
  • x509 cert parsing, support for FIDO-related extensions, and NIST Public Key Interoperability Test Suite (PKITS) chain validation (from pki.js)
  • Returns parsed and validated data, along with extra audit data for risk engines
  • Support both CommonJS (require) and ESM (import) natively

Example

Import Library using CommonJS:

const { Fido2Lib } = require("fido2-lib");

// create a new instance of the library
const f2l = new Fido2Lib(/* ... */);

Import Library using ESM-syntax:

// Node
import { Fido2Lib } from "fido2-lib";

// ... or Deno - Replace x.y.z with current version
// import { Fido2Lib } from "https://cdn.jsdelivr.net/npm/fido2-lib@x.y.z/dist/main.js";


// create a new instance of the library
const f2l = new Fido2Lib(/* ... */);

Instantiate Library (Complex):

// could also use one or more of the options below,
// which just makes the options calls easier later on:
const f2l = new Fido2Lib({
    timeout: 42,
    rpId: "example.com",
    rpName: "ACME",
    rpIcon: "https://example.com/logo.png",
    challengeSize: 128,
    attestation: "none",
    cryptoParams: [-7, -257],
    authenticatorAttachment: "platform",
    authenticatorRequireResidentKey: false,
    authenticatorUserVerification: "required"
});

Registration:

const registrationOptions = await f2l.attestationOptions();

// make sure to add registrationOptions.user.id
// save the challenge in the session information...
// send registrationOptions to client and pass them in to `navigator.credentials.create()`...
// get response back from client (clientAttestationResponse)

const attestationExpectations = {
    challenge: "33EHav-jZ1v9qwH783aU-j0ARx6r5o-YHh-wd7C6jPbd7Wh6ytbIZosIIACehwf9-s6hXhySHO-HHUjEwZS29w",
    origin: "https://localhost:8443",
    factor: "either"
};
const regResult = await f2l.attestationResult(clientAttestationResponse, attestationExpectations); // will throw on error

// registration complete!
// save publicKey and counter from regResult to user's info for future authentication calls

Authentication:

const authnOptions = await f2l.assertionOptions();

// add allowCredentials to limit the number of allowed credential for the authentication process. For further details refer to webauthn specs: (https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialrequestoptions-allowcredentials).
// save the challenge in the session information...
// send authnOptions to client and pass them in to `navigator.credentials.get()`...
// get response back from client (clientAssertionResponse)

const assertionExpectations = {
    // Remove the following comment if allowCredentials has been added into authnOptions so the credential received will be validate against allowCredentials array.
    // allowCredentials: [{
    //     id: "lTqW8H/lHJ4yT0nLOvsvKgcyJCeO8LdUjG5vkXpgO2b0XfyjLMejRvW5oslZtA4B/GgkO/qhTgoBWSlDqCng4Q==",
    //     type: "public-key",
    //     transports: ["usb"]
    // }],
    challenge: "eaTyUNnyPDDdK8SNEgTEUvz1Q8dylkjjTimYd5X7QAo-F8_Z1lsJi3BilUpFZHkICNDWY8r9ivnTgW7-XZC3qQ",
    origin: "https://localhost:8443",
    factor: "either",
    publicKey: "-----BEGIN PUBLIC KEY-----\n" +
        "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERez9aO2wBAWO54MuGbEqSdWahSnG\n" +
        "MAg35BCNkaE3j8Q+O/ZhhKqTeIKm7El70EG6ejt4sg1ZaoQ5ELg8k3ywTg==\n" +
        "-----END PUBLIC KEY-----\n",
    prevCounter: 362
};
const authnResult = await f2l.assertionResult(clientAssertionResponse, assertionExpectations); // will throw on error

// authentication complete!

For a real-life example, refer to OWASP Single Sign-On.

Migration from v2 to v3

Generally v3 is assumed to be completely compatible with v2 - compatibility should have increased. As many inner workings have been changed, please verify that your application still works with v3 and report issues, if you newly encounter bugs.

Work for this project was supported by Adam Power.