Giter VIP home page Giter VIP logo

fido2-lib's People

Contributors

apowers313 avatar codydfns avatar dependabot[bot] avatar efabris avatar gaizeror avatar goldenbearkin avatar hexagon avatar hsmdbc avatar jamescullum avatar jbyoshi avatar jedrivisser avatar kuboon avatar lilac-milena avatar martinord avatar oplik0 avatar pathtolife avatar perongh avatar popeeyy avatar qwtel avatar randomprogramming avatar ryanhopkins7 avatar segevmalool avatar snyk-bot avatar sojinsamuel avatar step-security-bot avatar tomerdavid-transmit avatar vigan-abd avatar wesseldr avatar wparad avatar zaninandrea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fido2-lib's Issues

Soft token for testing

Do you know if there's a soft token library available that would be suitable to use for testing?

At the moment I use webdriverio and Firefox, which is fine but requires me to have a hard token plugged in and press the button multiple times on each test.

For one of my projects I saved the responses and then replayed them (ignoring replay errors).

However it would by nice to have a library/program which would act like a hard token.

@apowers313 what do you use for testing?

Wrong Check of UP flag

Hello,

Both in the Assertion and Attestation validation the WebAuthn guideline specify these controls:

  • Verify that the User Present bit of the flags in authData is set.
  • If user verification is required for this registration, verify that the User Verified bit of the flags in authData is set.

The library get the flags to be verified from the expectations that are parsed by this function:

function factorToFlags(expectedFactor, flags) {
	// var flags = ["AT"];
	flags = flags || [];
	switch (expectedFactor) {
		case "first":
			flags.push("UV");
			break;
		case "second":
			flags.push("UP");
			break;
		case "either":
			flags.push("UP-or-UV");
			break;
		default:
			throw new TypeError("expectedFactor should be 'first', 'second' or 'either'");
	}
	return flags;
}

The flags in the authnrData are parsed by these lines in "parseAuthenticatorData(authnrDataArrayBuffer)":

	if (flags & 0x01) flagsSet.add("UP");
	if (flags & 0x02) flagsSet.add("RFU1");
	if (flags & 0x04) flagsSet.add("UV");
	if (flags & 0x08) flagsSet.add("RFU3");
	if (flags & 0x10) flagsSet.add("RFU4");
	if (flags & 0x20) flagsSet.add("RFU5");
	if (flags & 0x40) flagsSet.add("AT");
	if (flags & 0x80) flagsSet.add("ED");

Finally the following function validates the flags:

async function validateFlags() {
	var expectedFlags = this.expectations.get("flags");
	var flags = this.authnrData.get("flags");

	for (let expFlag of expectedFlags) {
		if (expFlag === "UP-or-UV") {
			if (flags.has("UP") || flags.has("UV")) {
				continue;
			} else {
				throw new Error("expected User Presence (UP) or User Verification (UV) flag to be set and neither was");
			}
		}

		if (!flags.has(expFlag)) {
			throw new Error(`expected flag was not set: ${expFlag}`);
		}
	}

	this.audit.journal.add("flags");

	return true;
}

These controls allow UP flag to be not set while it's mandatory, as specified in the WebAuthn docs reported above.

In my opinion the "factorToFlags()" should be changed in order to always put UP flag in the array. Additionlly the factor "either" and "second" are not necessary. The function factorToFlags() could be rewritten in this way:

function factorToFlags(expectedFactor, flags) {
	// var flags = ["AT"];
	flags = flags || [];

	switch (expectedFactor) {
		case "first":
			flags.push("UP");
			flags.push("UV");
			break;
		case "second":
			flags.push("UP");
			break;
		case "either":
			flags.push("UP-or-UV");
			break;
		default:
			throw new TypeError("expectedFactor should be 'first', 'second' or 'either'");
	}

	return flags;
}

and also the validateFlags() should be changed like following:

async function validateFlags() {
	var expectedFlags = this.expectations.get("flags");
	var flags = this.authnrData.get("flags");

	for (let expFlag of expectedFlags) {
		if (expFlag === "UP-or-UV") {
			if (flags.has("UV")) {
				if (flags.has("UP")) {
					continue;
				} else {
					throw new Error("expected User Presence (UP) flag to be set if User Verification (UV) is set");
				}
			} else if (flags.has("UP")) {
				continue;
			} else {
				throw new Error("expected User Presence (UP) or User Verification (UV) flag to be set and neither was");
			}
		}

		if (expFlag === "UV") {
			if (flags.has("UV")) {
				if (flags.has("UP")) {
					continue;
				} else {
					throw new Error("expected User Presence (UP) flag to be set if User Verification (UV) is set");
				}
			} else {
				throw new Error(`expected flag was not set: ${expFlag}`);
			}
		}

		if (!flags.has(expFlag)) {
			throw new Error(`expected flag was not set: ${expFlag}`);
		}
	}

	this.audit.journal.add("flags");

	return true;
}

Do you agree with me? If so I can do a pull request to fix this.

Enrico Fabris.

Current status of this repo

I recently stared using this repo, however it seems the be stale, there are many open PR's solving various issues, @apowers313 is there any chance some of these can be merged, or could someone be appointed to manage this repo?

Is MDS3 supported?

Hi, MDS2 is going to be deprecated this month, may I know if FIDO Metadata Service 3 is supported? If no, is there any roadmap to support MDS3?

Doesn't install on Node 10

Because of PeculiarVentures/node-webcrypto-ossl#121

david@david-Latitude-E6440:/tmp$ npm install node-webcrypto-ossl

> [email protected] install /tmp/node_modules/node-webcrypto-ossl
> node-gyp rebuild

make: Entering directory '/tmp/node_modules/node-webcrypto-ossl/build'
  CXX(target) Release/obj.target/nodessl/src/main.o
  CXX(target) Release/obj.target/nodessl/src/core/bn.o
../src/core/bn.cpp: In function โ€˜long unsigned int read_word_padded(const BIGNUM*, size_t)โ€™:
../src/core/bn.cpp:33:17: error: invalid use of incomplete type โ€˜const BIGNUM {aka const struct bignum_st}โ€™
  BN_ULONG l = in->d[constant_time_select_ulong(
                 ^~
In file included from /home/david/.node-gyp/10.0.0/include/node/openssl/bn.h:32:0,
                 from ../src/core/bn.h:5,
                 from ../src/core/bn.cpp:1:
/home/david/.node-gyp/10.0.0/include/node/openssl/ossl_typ.h:80:16: note: forward declaration of โ€˜BIGNUM {aka struct bignum_st}โ€™
 typedef struct bignum_st BIGNUM;
                ^~~~~~~~~
../src/core/bn.cpp:34:29: error: invalid use of incomplete type โ€˜const BIGNUM {aka const struct bignum_st}โ€™
   constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
                             ^~
In file included from /home/david/.node-gyp/10.0.0/include/node/openssl/bn.h:32:0,
                 from ../src/core/bn.h:5,
                 from ../src/core/bn.cpp:1:
/home/david/.node-gyp/10.0.0/include/node/openssl/ossl_typ.h:80:16: note: forward declaration of โ€˜BIGNUM {aka struct bignum_st}โ€™
 typedef struct bignum_st BIGNUM;
                ^~~~~~~~~
../src/core/bn.cpp:34:43: error: invalid use of incomplete type โ€˜const BIGNUM {aka const struct bignum_st}โ€™
   constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
                                           ^~
In file included from /home/david/.node-gyp/10.0.0/include/node/openssl/bn.h:32:0,
                 from ../src/core/bn.h:5,
                 from ../src/core/bn.cpp:1:
/home/david/.node-gyp/10.0.0/include/node/openssl/ossl_typ.h:80:16: note: forward declaration of โ€˜BIGNUM {aka struct bignum_st}โ€™
 typedef struct bignum_st BIGNUM;
                ^~~~~~~~~
../src/core/bn.cpp:36:62: error: invalid use of incomplete type โ€˜const BIGNUM {aka const struct bignum_st}โ€™
  return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
                                                              ^~
In file included from /home/david/.node-gyp/10.0.0/include/node/openssl/bn.h:32:0,
                 from ../src/core/bn.h:5,
                 from ../src/core/bn.cpp:1:
/home/david/.node-gyp/10.0.0/include/node/openssl/ossl_typ.h:80:16: note: forward declaration of โ€˜BIGNUM {aka struct bignum_st}โ€™
 typedef struct bignum_st BIGNUM;
                ^~~~~~~~~
../src/core/bn.cpp: In function โ€˜int BN_bn2bin_padded(uint8_t*, size_t, const BIGNUM*)โ€™:
../src/core/bn.cpp:49:16: error: invalid use of incomplete type โ€˜const BIGNUM {aka const struct bignum_st}โ€™
  if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
                ^~
In file included from /home/david/.node-gyp/10.0.0/include/node/openssl/bn.h:32:0,
                 from ../src/core/bn.h:5,
                 from ../src/core/bn.cpp:1:
/home/david/.node-gyp/10.0.0/include/node/openssl/ossl_typ.h:80:16: note: forward declaration of โ€˜BIGNUM {aka struct bignum_st}โ€™
 typedef struct bignum_st BIGNUM;
                ^~~~~~~~~
../src/core/bn.cpp: At global scope:
../src/core/bn.cpp:22:12: warning: โ€˜int constant_time_le_size_t(size_t, size_t)โ€™ defined but not used [-Wunused-function]
 static int constant_time_le_size_t(size_t x, size_t y) {
            ^~~~~~~~~~~~~~~~~~~~~~~
../src/core/bn.cpp:14:17: warning: โ€˜long unsigned int constant_time_select_ulong(int, long unsigned int, long unsigned int)โ€™ defined but not used [-Wunused-function]
 static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~
nodessl.target.mk:134: recipe for target 'Release/obj.target/nodessl/src/core/bn.o' failed
make: *** [Release/obj.target/nodessl/src/core/bn.o] Error 1
make: Leaving directory '/tmp/node_modules/node-webcrypto-ossl/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/home/david/.nvm/versions/node/v10.0.0/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:258:23)
gyp ERR! stack     at ChildProcess.emit (events.js:182:13)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:225:12)
gyp ERR! System Linux 4.15.0-20-generic
gyp ERR! command "/home/david/.nvm/versions/node/v10.0.0/bin/node" "/home/david/.nvm/versions/node/v10.0.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /tmp/node_modules/node-webcrypto-ossl
gyp ERR! node -v v10.0.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok 
npm WARN enoent ENOENT: no such file or directory, open '/tmp/package.json'
npm WARN tmp No description
npm WARN tmp No repository field.
npm WARN tmp No README data
npm WARN tmp No license field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] install script.

attestationResult docs

The docs say this takes response.authenticatorData. Should it be response.attestationObject ?

load MDS data

Support functions for loading and validating MDS data, and using MDS data for validating cert chains.

support for u2f migrated appId

According to yubico docs in case of u2f migrated credentials the assertion challenge should include also appid extension. In that case the credential manager in browser uses appid as rpId, and this is failing in validation of checkRpId or validateRpIdHash because it requires rp id to be a full domain aand not url, however credential manager uses full url of appid in such cases as rpId.

Flow description:
image

Cannot upgrade pkijs past 2.1.60

Cannot figure this one out...

All is ok with [email protected] - Error with [email protected]

    verifyCertChain ...
      rejects on empty arguments ... ok (13ms)
      works for MDS2 ... FAILED (93ms)
        Error: No revocation values found for one of certificates: No valid CRLs found
                                throw new Error(res.resultMessage);
                                      ^
            at Function.verifyCertChain (/fido2-lib/lib/certUtils.js:587:10)

Failing test:

it("works for MDS2", function() {

Related certs available here:

const mdsRootCert = "-----BEGIN CERTIFICATE-----\n" +

Failing line:

throw new Error(res.resultMessage);

Could it be related to this change in CertificateChainValidationEngine.js? Or something else?

image

Update after 2.8.3 to 3.1.0 or later

After updating the library to 2.8.3 from 3.1.0.

We observer the following error:

error parsing ASN.1 

We have not changed any parts of our code.

We use yubikeys 5 with this library.

Add support for `fmt: 'apple'`

Hi all,

Is it possible to mainline the Apple attestation format into this to create a sort of "commercial omnibus" canonical node library?

This might help/promote adoption?!

If you are open to external contribution and contributors -- I will definitely submit a PR for this!

Thanks,
David

Feature request: Support for Deno/ESM

Would be really nice if this lib supported Deno and moved away from CommonJS!

I'm experimenting on porting fido2-lib to a dual mode Node/Deno-lib on my own, and migrating everything to ES6 while at it. But I guess the changes are too big to "pull back" into this lib (?).

What need to be done/What I'm experimenting on:

  • Reduce usage on Node-specific stuff; Replace Buffer with ArrayBuffer, replace crypto with webcrypto/subtle where possible
  • Favor zero subdependency dependencies when available, bundle and modify them if dependencies depend on eachother
  • Favor dependencies that already support import/export module pattern.
  • Favor dependencies that support Deno and/or browser usage.
  • Pay attention to using one, and only one, implementation of each function. Also make sure that dependencies use the same implementations (base64 is a good example, i found at least 6 different implementations in fido2-lib plus it's dependencies)

Check out https://github.com/Hexagon/webauthn for ideas and inspiration, and please drop an issue of you find anything that doesn't look ok :)


Update 2022-04-25

Status of @hexagon/webauthn - Dual platform - Deno first - Node built

https://github.com/Hexagon/webauthn is pretty much in sync with fido2-lib now.

  • All features are implemented
  • All Node tests implemented
  • Deno first approach, where dependencies are imported by Deno, and a platform independent bundle with zero dependencies is built (dist/webauthn.js). The bundle work in both Deno and Node, and it should technically work in browser too.
  • Code style (lint) upgraded to current recommended standards
  • Etc ...

Status of hexagon/fido2-lib fork , Dual platform - Node and Deno codebase

I've also submitted a pull request with a Node-first/Dual platform version of fido2-lib at PR #80

Two alternatives, both support both Deno and Node :)

Can we add attestations in u2fRootCerts.js

I'm having discussions with a FIDO2 authenticator manufacturer to get their public attestation key.

If they allow me can I PR the addition of the key in u2fRootCerts.js?

Would that make https://webauthn.org/ able to validate the attestation?

Right now it's giving me the boring:

warning: {
    attesation-not-validated: "could not validate attestation because the root attestation certification could not be found",
},

New fields in clientDataJSON

clientDataJson in Chrome Canary Version 68.0.3438.3 now has a hashAlgorithm property. Should use this field if it is present.

{
"rawClientDataJson":"{\"challenge\":\"ICFGoPRC4FMPIKSX5cexUVwBzEX5H9KWnRYQZVCiGpesn59PzizxgLYQS_QRIy-TBYsRg1_zJ4hLpTNLeLUFiA\",\"clientExtensions\":{},\"hashAlgorithm\":\"SHA-256\",\"origin\":\"https://localhost:8443\",\"type\":\"webauthn.create\"}",
}

register attestation format

Make attestation formats into modules that can be registered -- enables loading of new attestation formats. Existing attestation formats should use this interface, but should probably be included by default. Also include a function to deregister attestation formats (so that default formats can be unloaded).

Attestation formats comes as "None"

Hi Adam,

I am trying to receive TPM attestation statement and that's why setting attestation:"direct" in create() but still fmt in response comes as "none". How we can instruct Authenticator (Windows Hello) to use TPM as cryptographic engine.
Does none means TPM is not used for cryptographic operation?
AAGUID coming as {08987058-cadc-4b81-b6e1-30de50dcbe96} which indicates hardware authenticator.

Regards,
Pooja

In some cases ECDSA signatures are not validated properly.

ECDSA signatures in ASN.1/DER format with an R or S that is not 32 bytes (this happens when the R/S have some number of leading zeros), are not verified properly.

This test can be used to reproduce this behavior:

// Testing lib
import * as chai from "chai";
import * as chaiAsPromised from "chai-as-promised";

import crypto from "crypto";
import { Fido2Lib } from "../lib/main.js";

chai.use(chaiAsPromised.default);
const assert = chai.assert;

const sha256 = (data) => {
	return crypto.createHash("sha256").update(data).digest("hex");
};

const base64url = (buf) => {
	return Buffer.from(buf).toString("base64url");
};
const base64urlToBuffer = (str) => {
	return Buffer.from(str, "base64url");
};
const base64urlToArrayBuffer = (str) => {
	const buf = base64urlToBuffer(str);
	return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
};

const generateSignature = (authenticatorData, clientData, privateKey) => {
	const dataHash = sha256(clientData);
	const authenticatorDataHex = base64urlToBuffer(authenticatorData).toString("hex");
	let signature;
	do {
		signature = new Uint8Array(
			crypto.sign(
				null,
				Buffer.from(authenticatorDataHex + dataHash, "hex"),
				privateKey
			)
		);
	} while(signature[3] >= 32);

	return base64url(signature);
};

const generateAuthenticatorData = () => {
	const flags = 5;
	const counter = 15;

	const rpidHash = sha256("localhost", "hex");
	const authData = Buffer.from(
		rpidHash + flags.toString(16).padStart(2, "0") + counter.toString(16).padStart(8, "0"),
		"hex"
	);

	return base64url(authData);
};

const generateInput = (privateKey) => {
	const challenge = sha256("SomeRandomChallenge");
	const clientData = JSON.stringify({
		type: "webauthn.get",
		challenge: base64url(challenge),
		origin: "http://localhost:3000",
		crossOrigin: false,
	});

	const authenticatorData = generateAuthenticatorData();

	return {
		credId: base64url("RandomCredId"),
		clientData: base64url(clientData),
		authenticatorData: authenticatorData,
		signature: generateSignature(authenticatorData, clientData, privateKey),
		userHandle: base64url("RandomUserId"),
	};
};

describe("assertion", function() {
	it("can verify a ECDSA signature with non-standard r / s", async function() {
		const key = crypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
		const privateKey = key.privateKey.export({ type: "pkcs8", format:"pem" });
		const publicKey = key.publicKey.export({ type: "spki", format:"pem" });
		const input = generateInput(privateKey);
		const fido2 = new Fido2Lib({
			timeout: 42,
			rpId: "localhost",
			rpName: "localhost",
			challengeSize: 128,
			attestation: "direct",
			cryptoParams: [-7, -257],
			authenticatorRequireResidentKey: true,
			authenticatorUserVerification: "required",
		});
	
		const challenge = sha256("SomeRandomChallenge");
		const result = await fido2.assertionResult(
			{
				rawId: base64urlToArrayBuffer(input.credId),
				response: {
					clientDataJSON: input.clientData,
					authenticatorData: base64urlToArrayBuffer(input.authenticatorData),
					signature: input.signature,
					userHandle: input.userHandle,
				},
			},
			{
				rpId: "localhost",
				challenge: base64url(challenge),
				origin: "http://localhost:3000",
				factor: "first",
				publicKey: publicKey,
				prevCounter: 1,
				userHandle: input.userHandle,
			}
		);
		assert.strictEqual(result.audit.validRequest, true);
		assert.strictEqual(result.audit.validExpectations, true);
	});
});

Does not support self attestation

The following error occurred when using MacBook TouchID as a authenticator.

Error: Server responed with error. The message is: packed attestation: self attestation not implemented, please open a GitHub issue.

Looks like fido2-lib doesn't support self-attestation.So we can not use TouchID as a authenticator.

Cannot use with caBLE

Error: expected transports of allowCredentials[0] to be string with value 'usb', 'nfc', 'ble', 'internal' or null
    at Fido2AssertionResult.validateExpectations (https://cdn.jsdelivr.net/npm/[email protected]/dist/main.js:53854:31)?

When using Chrome on computer, with a remote Android device as security key (over ble)- getTransports() return cable, which is not allowed by fido2-lib

Error: packed attestation: unknown algorithm: -257 with windows Hello

Library works great with chrome+ android phone as mfa, but when trying to register with windows hello I get: Error: packed attestation: unknown algorithm: -257
node_modules/fido2-lib/lib/attestations/packed.js:45:9

Is there any special configuration to setup for windows hello to work?

Support for Android/iOS authenticator?

Found this project as the most full FIDO2 implementation but can't make it work for Android mobile app case.

The attestationResult function throws the origin was malformatted error because the origin is not a valid web-URL and not started with https
The clientDataJSON is following for attestation and the same, but with "type": "webauthn.get" for the assert:

{
    "androidPackageName": "com.example.app",
    "challenge": "CvPFgfKYZCkviLwzieQZBArgORy6ayCZ8ModjHYrl24FG_uzdSZkXEFBHpGPJ9agV9XksMeVyUkDKCg_-ZhCmOO1_JT-BAK52bjY60gSsx291Piqc30haY-Cf93levthvoQQG3YJ8yOALVS6I1VNEo23Z7vOpIXoloXauAMGN98",
    "origin": "android:apk-key-hash:-sYXRdwJA3hvue3mKpYrOZ9zSPC7b4mbgzJmdZEDO5w",
    "type": "webauthn.create",
}

Can some one advise, please, if it possible to configure this library or the short way to extend it to make it work?

Incorrect function

Seems you at least incorrectly named this function. And in order to get serialNumber would could use this code:

import { bufferToHexCodes } from "pvutils";
const serialNumber = bufferToHexCodes(certificate.serialNumber.valueBlock.valueHex);

or this one:

const serialNumber = certificate.serialNumber.valueBlock.toString(); // for decimal representation, even for huge serial numbers

Use Native webcrypto

I was wondering if we could use native webcrypto (available since Node 15).

This is because the node-webcrypto-ossl package has really old dependencies (using node-gyp 3.8.0 which uses python2)

Anyway since the browsers have to support fido on the client side also, I think it is worthwhile to also let the backend require a higher node version.

Android SafetyNet not working

I tested on production the android-safetynet attestation. However, it is not working as currently it is not doing any of the checks required by WebAuthn (https://www.w3.org/TR/webauthn/#android-safetynet-attestation) nor the androidSafetyNetValidateFn() is returning true.

I also detected this function also needs to include the changes in the journal for it work.

I'm making a PR with this tested changes here and in @JamesCullum fork. The changes woul be, namely:

  • return true if no errors
  • perform nonce and payload checks
  • add the verified checks to journal

v2.2.0

I see package.json is at 2.2.0 but npm is at 2.1.1.
Just wondered if you forgot to publish.
No worries if it's work in progress, feel free to close immediately.

Error registering a security key when requesting resident key

Hi there,

I was interested in using the standard to implement both passwordless login as well as usernameless login, so I created a demo for it which allowed both forms: https://github.com/MxBlu/fido-poc

Unfortunately I've found that when requiring a resident key, the response cannot be parsed by the server using attestationResult():

Error: couldn't parse authenticator.authData.attestationData CBOR: Error: Data read, but end of buffer not reached
    at PublicKey.fromCose (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:1010:10)
    at parseAuthenticatorData (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:2898:19)
    at parseAuthnrAttestationResponse (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:2845:12)
    at Fido2AttestationResult.parse (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:3035:27)
    at async Fido2AttestationResult.create (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:3004:3)
    at async Function.create (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:3050:10)
    at async Fido2Lib.attestationResult (\x\fido-poc\backend\node_modules\fido2-lib\dist\main.cjs:5465:10)

I can debug JS code, but decoding the CBOR response is out of my expertise sadly. Any insight would be much appreciated!

The issue can be reproduced with my demo by setting FIDO2_REQUIRE_RESIDENT_KEY = true in backend/src/constants.ts.

Options object passed to nagivator.credentials.create():

{
  "publicKey": {
    "rp": {
      "name": "MxBlue Server",
      "id": "fido.mxblue.net.au"
    },
    "user": {
      "id": {},
      "displayName": "mxblue",
      "name": "mxblue-150822-3"
    },
    "challenge": {},
    "pubKeyCredParams": [
      {
        "type": "public-key",
        "alg": -7
      },
      {
        "type": "public-key",
        "alg": -257
      }
    ],
    "timeout": 120000,
    "attestation": "none",
    "authenticatorSelection": {
      "requireResidentKey": true
    }
  }
}

Environment details:

  • Browser: Version 104.0.5112.81 (Official Build) (64-bit)
  • OS: Windows 11 Insider Build 25179.1000
  • Security key: Yubikey 5

error types

Create new error types for parsing, validation errors, so that server can return right HTTP status code depending on the type of failure.

Authenticating from multiple devices

I am having trouble in understanding how exactly one would authenticate a user that wants to use multiple devices to log in.. Lets say a user has a mac laptop with touchId and a windows pc with a security key. I register on my laptop using my touch id. That generates a public key which is then saved, and I can log in just fine on my laptop. Now I switch to my PC and want to register. I understand that there is a allowCredentials field, but I am not sure what is its use exactly. If I try to register on my PC, and save just the credential ID of that pc, but I try to log in using the public key generated from the laptop, I am guessing that will just fail, right? Would I need to also save an array of public keys, and try to authenticate with each one of them? Or maybe save which credential ID matches to which public key? This is just theory crafting as I unfortunately don't have multiple webauth capable devices around me to test right now, so sorry if this may be a dumb question

Is there a reason to warn users about native crypto?

For some reason the library uses default console warn facility to print a message "Native crypto is enabled" without any explanation why this warning exists or if we expect users to do anything about this.

console.warn("[FIDO2-LIB] Native crypto is enabled");

can be found in at least 2 places in the codebase:

console.warn("[FIDO2-LIB] Native crypto is enabled");

console.warn("[FIDO2-LIB] Native crypto is enabled");

If this is needed information to the users we should improve the message to be more actionable OR we should remove the message.

authenticatorSelectionCriteria and attachment are incorrect property names.

Fixed in pull request: #32

authenticatorSelectionCriteria
The field authenticatorSelection is of type authenticatorSelectionCriteria but the name should be authenticatorSelection according to the w3c: authenticatorselection Changing the property name will make the userVerification working. Set the property to "required" and it enforces a PIN setup during attestation and asks for a pin during assertion. According to specs :-)
authenticatorAttachment
Changed property "attachment" into "authenticatorAttachment", is now also working for "platform" and "cross-platform" also tested and working now with both Solo & Yubi... well both devices are rejected when in platform mode and that is according to specs :-)
Unit tests updated

Error in an environment where version 3 python is installed as a python command

When installing fido2-lib, if the python command is version 3, the following error will occur.

$ git clone https://github.com/apowers313/fido2-lib.git
$ cd fido2-lib/
$ npm install
npm WARN deprecated [email protected]: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated [email protected]: This package is unmaintained. Use @sinonjs/formatio instead
npm WARN deprecated [email protected]: to-iso-string has been deprecated, use @segment/to-iso-string instead.
npm WARN deprecated [email protected]: This package has been deprecated in favour of @sinonjs/samsam
npm WARN deprecated [email protected]: This package has been deprecated in favour of @sinonjs/samsam
npm WARN deprecated [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated [email protected]: This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.

> [email protected] install /private/tmp/fido2-lib/node_modules/node-webcrypto-ossl
> node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Command failed: /Users/kg0r0/venv/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Socket.stream.socket.on (internal/child_process.js:389:11)
gyp ERR! stack     at Socket.emit (events.js:189:13)
gyp ERR! stack     at Pipe._handle.close (net.js:597:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /private/tmp/fido2-lib/node_modules/node-webcrypto-ossl
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/kg0r0/.npm/_logs/2019-08-13T14_38_15_118Z-debug.log

"found 10 vulnerabilities" it's only istanbul 1.1 producing that.. please update to nyc

Hi,

During npm install, it looks very "scary" with found 10 vulnerabilities (1 low, 6 moderate, 2 high, 1 critical), however its only good old obsolete istanbul generating all these depreciation errors. I'm lacking any knowledge of the auto build street what the impact is if I replace this with nyc.

Is there anybody who could just upgrade this to nyc 14.x so we get rid of these depreciation warnings... please?

JWR

Node 16 build error

> yarn add fido2-lib
yarn add v1.22.10
[1/4] ๐Ÿ”  Resolving packages...
warning fido2-lib > node-jose > [email protected]: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
[2/4] ๐Ÿšš  Fetching packages...
[3/4] ๐Ÿ”—  Linking dependencies...
warning " > [email protected]" has incorrect peer dependency "react@^17.0.2".
warning " > [email protected]" has incorrect peer dependency "react-dom@^17.0.2".
warning "@types/next > next > @next/[email protected]" has incorrect peer dependency "react@^17.0.2".
warning "@types/next > next > @next/[email protected]" has incorrect peer dependency "react-dom@^17.0.2".
warning "@types/next > next > [email protected]" has incorrect peer dependency "[email protected] || 16.x.x || 17.x.x".
warning "@types/next > next > [email protected]" has incorrect peer dependency "react@^16.8.0 || ^17.0.0".
warning " > [email protected]" has incorrect peer dependency "react@>=16.x <=17.x".
warning " > [email protected]" has incorrect peer dependency "react-dom@>=16.x <=17.x".
warning "next-mdx-remote > @mdx-js/[email protected]" has incorrect peer dependency "react@^16.13.1 || ^17.0.0".
warning " > [email protected]" has incorrect peer dependency "next@^8.1.1-canary.54 || ^9.0.0 || ^10.0.0".
warning " > [email protected]" has incorrect peer dependency "react@^16.0.0 || ^17.0.0".
warning " > [email protected]" has incorrect peer dependency "react-dom@^16.0.0 || ^17.0.0".
warning "eslint-config-next > @typescript-eslint/parser > @typescript-eslint/typescript-estree > [email protected]" has unmet peer dependency "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta".
[4/4] ๐Ÿ”จ  Building fresh packages...
[-/3] โ „ waiting...
[-/3] โ „ waiting...
error /Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments: 
Directory: /Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl
Output:
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | darwin | x64
gyp info find Python using Python version 3.9.5 found at "/usr/local/opt/[email protected]/bin/python3.9"
(node:12667) [DEP0150] DeprecationWarning: Setting process.config is deprecated. In the future the property will be read-only.
(Use `node --trace-deprecation ...` to show where the warning was created)
gyp info spawn /usr/local/opt/[email protected]/bin/python3.9
gyp info spawn args [
gyp info spawn args   '/Users/himself65/.nvm/versions/node/v16.4.0/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/Users/himself65/.nvm/versions/node/v16.4.0/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/Users/himself65/Library/Caches/node-gyp/16.4.0/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/Users/himself65/Library/Caches/node-gyp/16.4.0',
gyp info spawn args   '-Dnode_gyp_dir=/Users/himself65/.nvm/versions/node/v16.4.0/lib/node_modules/npm/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=/Users/himself65/Library/Caches/node-gyp/16.4.0/<(target_arch)/node.lib',
gyp info spawn args   '-Dmodule_root_dir=/Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl',
gyp info spawn args   '-Dnode_engine=v8',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.'
gyp info spawn args ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
  CXX(target) Release/obj.target/nodessl/src/main.o
Apple clang version 13.0.0 (clang-1300.0.18.6)
Target: x86_64-apple-darwin21.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.7.0 -Wundef-prefix=TARGET_OS_ -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj --mrelax-relocations -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fno-strict-return -fno-rounding-math -munwind-tables -faligned-alloc-unavailable -target-sdk-version=12.0 -fvisibility-inlines-hidden-static-local-var -target-cpu core2 -tune-cpu generic -debug-info-kind=standalone -dwarf-version=2 -debugger-tuning=lldb -target-linker-version 705 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0 -dependency-file ./Release/.deps/Release/obj.target/nodessl/src/main.o.d.raw -skip-unused-modulemap-deps -MT Release/obj.target/nodessl/src/main.o -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -D NODE_GYP_MODULE_NAME=nodessl -D USING_UV_SHARED=1 -D USING_V8_SHARED=1 -D V8_DEPRECATION_WARNINGS=1 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D _DARWIN_USE_64_BIT_INODE=1 -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS=64 -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D BUILDING_NODE_EXTENSION -I /Users/himself65/Library/Caches/node-gyp/16.4.0/include/node -I /Users/himself65/Library/Caches/node-gyp/16.4.0/src -I /Users/himself65/Library/Caches/node-gyp/16.4.0/deps/openssl/config -I /Users/himself65/Library/Caches/node-gyp/16.4.0/deps/openssl/openssl/include -I /Users/himself65/Library/Caches/node-gyp/16.4.0/deps/uv/include -I /Users/himself65/Library/Caches/node-gyp/16.4.0/deps/zlib -I /Users/himself65/Library/Caches/node-gyp/16.4.0/deps/v8/include -I ../../nan -I/usr/local/include -stdlib=libc++ -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -O3 -Wall -Wendif-labels -W -Wno-unused-parameter -Wno-reorder-init-list -Wno-implicit-int-float-conversion -Wno-c99-designator -Wno-final-dtor-non-final-class -Wno-extra-semi-stmt -Wno-misleading-indentation -Wno-quoted-include-in-framework-header -Wno-implicit-fallthrough -Wno-enum-enum-conversion -Wno-enum-float-conversion -Wno-elaborated-enum-base -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl/build -ferror-limit 19 -stack-protector 1 -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fno-rtti -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fmax-type-align=16 -fcommon -vectorize-loops -vectorize-slp -clang-vendor-feature=+nullptrToBoolConversion -clang-vendor-feature=+messageToSelfInClassMethodIdReturnType -clang-vendor-feature=+disableInferNewAvailabilityFromInit -clang-vendor-feature=+disableNeonImmediateRangeCheck -clang-vendor-feature=+disableNonDependentMemberExprInCurrentInstantiation -fno-odr-hash-protocols -clang-vendor-feature=+revert09abecef7bbf -mllvm -disable-aligned-alloc-awareness=1 -mllvm -enable-dse-memoryssa=0 -o Release/obj.target/nodessl/src/main.o -x c++ ../src/main.cpp
clang -cc1 version 13.0.0 (clang-1300.0.18.6) default target x86_64-apple-darwin21.0.0
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/src"
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/deps/openssl/config"
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/deps/openssl/openssl/include"
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/deps/uv/include"
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/deps/zlib"
ignoring nonexistent directory "/Users/himself65/Library/Caches/node-gyp/16.4.0/deps/v8/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
 /Users/himself65/Library/Caches/node-gyp/16.4.0/include/node
 ../../nan
 /usr/local/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.
In file included from ../src/main.cpp:1:
In file included from ../src/node/common.h:4:
In file included from ../src/node/../core/common.h:8:
In file included from ../../nan/nan.h:56:
In file included from /Users/himself65/Library/Caches/node-gyp/16.4.0/include/node/node.h:63:
In file included from /Users/himself65/Library/Caches/node-gyp/16.4.0/include/node/v8.h:30:
/Users/himself65/Library/Caches/node-gyp/16.4.0/include/node/v8-internal.h:454:38: error: no template named 'remove_cv_t' in namespace 'std'; did you mean 'remove_cv'?
            !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
                                ~~~~~^~~~~~~~~~~
                                     remove_cv
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/type_traits:776:50: note: 'remove_cv' declared here
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_cv
                                                 ^
1 error generated.
make: *** [Release/obj.target/nodessl/src/main.o] Error 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/Users/himself65/.nvm/versions/node/v16.4.0/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack     at ChildProcess.emit (node:events:394:28)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
gyp ERR! System Darwin 21.0.0
gyp ERR! command "/Users/himself65/.nvm/versions/node/v16.4.0/bin/node" "/Users/himself65/.nvm/versions/node/v16.4.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/himself65/Code/Github/himself65.github.io/node_modules/node-webcrypto-ossl
gyp ERR! node -v v16.4.0
gyp ERR! node-gyp -v v7.1.2

Add support for authenticator extension

Hi @JamesCullum,

Currently the parseAuthenticatorData function throws and error if the "ED" flag is present in the authenticator data.

This behaviour blocks the parsing of the authenticatorData and the library fails.

I would like to propose a different approach: it's possible to parse the extension data as reported in this link and delegate the effective validation to a function in the validation process, as reported here. The reported validateExtensionData is very simple and in the future could be extended letting the user to provide their own function to validate extension data or could be improved to validate the most frequent extensions.

These changes allow to accept also authenticator data with extension.

What do you think? If you agree with me I'll complete the tests and then I'll create a PR.

Enrico.

In the case of localhost, this library returns an error like "origin should be https"

In the case of localhost, there should be no problem even if it is not https.

Please note: both create() and get() require a Secure Context (e.g. - the server is connected by https or is the localhost), and will not be available for use if the browser is not operating in a secure context.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

I think in the case of localhost should be excluded this error.
https://github.com/apowers313/fido2-lib/blob/7341fc49479bd736b1f1b57860bcec480d1ea744/lib/utils.js#L157-L159

MDS Issues

I was implementing MDS according to the documentation which gives this example:

var mc = Fido2Lib.createMdsCollection()
// download TOC from https://mds.fidoalliance.org ...
var tocObj = await mc.addToc(tocBase64);
tocObj.entries.forEach((entry) => {
    // download entry.url ...
    mc.addEntry(entryBase64);
});
Fido2Lib.setMdsCollection(mc); // performs validation
var entry = Fido2Lib.findEntry("4e4e#4005");

After downloading the TOC from the provided url, I discovered that the default certificate was not valid, so I added the one provided. From there, I ran into more issues. The structure seems to be completely different than what is coded. I decoded the JWT so I could take a look for myself what the returned structure is. The library expects a hash in all of the entries, but there is no hash entry to be found. All of the data is also in a "metadataStatement" property, which I made sure to account for in my modified code. However, authenticationAlgorithm and publicKeyAlgAndEncoding are arrays and are plural in the returned data as well. They are also already strings in the arrays, which is not checked in the string conversion, making them "invalid" when they are just of an unexpected type. Then, when I tried to use findEntry it did not work with the AAGUID, which I had to convert to a hex to get. This was because the AAGUIDs in the map contained dashes, but the library tried to convert the security key's AAGUID to a base64 which matched none of the values in the map.

I am using a YubiKey 5 with NFC to test. Am I doing something completely wrong or is there an issue with the library?

My code:

const cert = "CERT HERE"

axios.get("https://mds.fidoalliance.org").then(async (response) => {
    const tocObj = await mdsCollection.addToc(response.data, cert);

    tocObj.entries.forEach((entry) => {
        entry = entry.metadataStatement
        entry.authenticationAlgorithm = entry.authenticationAlgorithms[0]
        entry.publicKeyAlgAndEncoding = `ALG_KEY_${entry.publicKeyAlgAndEncodings[0].toUpperCase()}`

        mdsCollection.addEntry(base64url.encode(JSON.stringify(entry)));
    });

    Fido2Lib.addMdsCollection(mdsCollection);
})

To get it to work, I had to edit the library to check if the algorithms and attestationTypes were a string before attempting to convert them. I also had to create a hash for the TOC entries rather than attempting to rely on a non-existent one. Last, I had to convert all the AAGUIDs to not contain dashes so the security key's AAGUID (hex value) would match.

Allow nullable userHandle as stated in specs

Hi, I'm creating an issue here documenting the mismatch in specs and then making a quick PR.

What

I get the error when running assertionResult(response):
TypeError: expected 'response.userHandle' to be base64 String, ArrayBuffer, or undefined

response.userHandle is set to null

I modified the validateAssertionResponse function to validate the type internally

throw new TypeError(`expected 'response.userHandle' to be base64 String, ArrayBuffer, or undefined got ${req.response.userHandle}`);

which returns:
... got null

So I'm wondering if we should allow null? Any foreseen consequences?

Spec

According to the level 3 and level 2 docs, userHandle nullable, and should be accepted?
https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-userhandle
https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-userhandle
docs-nullable

Background

I'm using import { get } from '@github/webauthn-json/browser-ponyfill' to sign the decoded PublicKeyCredentialRequestOptions from the server. This PublicKeyCredentialRequestOptions contains a list of allowCredentials (~3), some of which do not correspond to resident keys.

The userHandle is only set if I sign using a residentKey, if not, I get the TypeError on the server side.
It may be good to allow null, if we agree this is applicable to spec.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.