Skip to main content
Module

x/fido2/test/ext.test.js

A node.js library for performing FIDO 2.0 / WebAuthn server functionality
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
// Testing libimport * as chai from "chai";
// Helpersimport * as sinon from "sinon";import { Fido2Lib } from "../lib/main.js";const assert = chai.assert;
describe("Fido2Lib extensions", function() { afterEach(function() { Fido2Lib.deleteAllExtensions(); });
it("exist", function() { assert.isFunction(Fido2Lib.addExtension); assert.isFunction(Fido2Lib.deleteAllExtensions); assert.isFunction(Fido2Lib.parseExtensionResult); assert.isFunction(Fido2Lib.validateExtensionResult); const mc = new Fido2Lib(); assert.isFunction(mc.generateExtensionOptions); assert.isFunction(mc.enableExtension); assert.isFunction(mc.disableExtension); assert.isFunction(mc.setExtensionOptions); });
describe("addExtension", function() { function fn() {}
it("throws if extName is not a string", function() { assert.throws(function() { Fido2Lib.addExtension(undefined, fn, fn, fn); }, Error, "expected 'extName' to be String, got: undefined"); });
it("throws if optionGeneratorFn isn't a function", function() { assert.throws(function() { Fido2Lib.addExtension("test", undefined, fn, fn); }, Error, "expected 'optionGeneratorFn' to be a Function, got: undefined"); });
it("throws if resultParserFn isn't a function", function() { assert.throws(function() { Fido2Lib.addExtension("test", fn, undefined, fn); }, Error, "expected 'resultParserFn' to be a Function, got: undefined"); });
it("throws if resultValidatorFn isn't a function", function() { assert.throws(function() { Fido2Lib.addExtension("test", fn, fn, undefined); }, Error, "expected 'resultValidatorFn' to be a Function, got: undefined"); });
it("adds the new extension", function() { Fido2Lib.addExtension("test", fn, fn, fn); });
it("throws if name is already set", function() { Fido2Lib.addExtension("test", fn, fn, fn);
assert.throws(function() { Fido2Lib.addExtension("test", fn, fn, fn); }, Error, "the extension 'test' has already been added"); }); });
describe("generateExtensionOptions", function() { let mc;
function fn() {}
beforeEach(function() { mc = new Fido2Lib(); });
it("throws if extName isn't a string", function() { assert.throws( function() { mc.generateExtensionOptions(undefined, "attestation"); }, Error, "expected 'extName' to be String, got: undefined", ); });
it("throws if extName isn't found", function() { assert.throws( function() { mc.generateExtensionOptions("test", "attestation"); }, Error, "valid extension for 'test' not found", ); });
it("throws if type isn't 'attestation' or 'assertion'", function() { assert.throws( function() { mc.generateExtensionOptions("test", "foo"); }, Error, "expected 'type' to be 'attestation' or 'assertion', got: foo", ); });
it("can generate for attestation", function(done) { function generateFn(name, type, options) { assert.strictEqual(name, "test"); assert.strictEqual(type, "attestation"); assert.isUndefined(options); done(); }
Fido2Lib.addExtension("test", generateFn, fn, fn); mc.generateExtensionOptions("test", "attestation"); });
it("can generate for assertion", function(done) { function generateFn(name, type, options) { assert.strictEqual(name, "test"); assert.strictEqual(type, "assertion"); assert.isUndefined(options); done(); }
Fido2Lib.addExtension("test", generateFn, fn, fn); mc.generateExtensionOptions("test", "assertion"); });
it("passes through options", function(done) { const opts = { foo: "bar", };
function generateFn(name, type, options) { assert.strictEqual(name, "test"); assert.strictEqual(type, "assertion"); assert.strictEqual(options, opts); done(); }
Fido2Lib.addExtension("test", generateFn, fn, fn); mc.generateExtensionOptions("test", "assertion", opts); }); });
describe("parseExtensionResult", function() { it("throws if extName isn't a string"); it("throws if extName isn't found"); it("throws if return value isn't valid"); it("returns parsed value"); });
describe("validateExtensionResult", function() { it("throws if extName isn't a string"); it("throws if extName isn't found"); it("throws if return value isn't true"); it("sets audit info"); });
describe("enableExtension", function() { let mc; function fn() {} beforeEach(function() { mc = new Fido2Lib(); });
it("throws if extName isn't a string", function() { assert.throws( function() { mc.enableExtension(undefined); }, Error, "expected 'extName' to be String, got: undefined", ); });
it("throws if extName isn't found", function() { assert.throws( function() { mc.enableExtension("test"); }, Error, "valid extension for 'test' not found", ); });
it("is disabled by default", function() { assert.isFalse(mc.extSet.has("test")); assert.isFalse(mc.extSet.has("test2")); Fido2Lib.addExtension("test", fn, fn, fn); Fido2Lib.addExtension("test2", fn, fn, fn); assert.isFalse(mc.extSet.has("test")); assert.isFalse(mc.extSet.has("test2")); mc = new Fido2Lib(); assert.isFalse(mc.extSet.has("test")); assert.isFalse(mc.extSet.has("test2")); });
it("sets extension to true", function() { Fido2Lib.addExtension("test", fn, fn, fn); mc = new Fido2Lib(); assert.isFalse(mc.extSet.has("test")); mc.enableExtension("test"); assert.isTrue(mc.extSet.has("test")); }); });
describe("disableExtension", function() { let mc; function fn() {} beforeEach(function() { mc = new Fido2Lib(); });
it("throws if extName isn't a string", function() { assert.throws( function() { mc.disableExtension(undefined); }, Error, "expected 'extName' to be String, got: undefined", ); });
it("throws if extName isn't found", function() { assert.throws( function() { mc.disableExtension("test"); }, Error, "valid extension for 'test' not found", ); });
it("sets extension to false", function() { Fido2Lib.addExtension("test", fn, fn, fn); mc = new Fido2Lib(); assert.isFalse(mc.extSet.has("test")); mc.enableExtension("test"); assert.isTrue(mc.extSet.has("test")); mc.disableExtension("test"); assert.isFalse(mc.extSet.has("test")); }); });
describe("setExtensionOptions", function() { let mc; function fn() {} beforeEach(function() { mc = new Fido2Lib(); });
it("throws if extName isn't a string", function() { assert.throws( function() { mc.setExtensionOptions(undefined); }, Error, "expected 'extName' to be String, got: undefined", ); });
it("throws if extName isn't found", function() { assert.throws( function() { mc.setExtensionOptions("test"); }, Error, "valid extension for 'test' not found", ); });
it("sets options", function() { const opts = { foo: "bar", };
Fido2Lib.addExtension("test", fn, fn, fn); mc.setExtensionOptions("test", opts); assert.isTrue(mc.extOptMap.has("test")); assert.strictEqual(mc.extOptMap.get("test"), opts); }); });
describe("attestationOptions", function() { let mc; function fn() {} beforeEach(function() { mc = new Fido2Lib(); });
it("calls generator", function() { const genSpy = sinon.stub(); const extVal = { beer: "good", }; genSpy.returns(extVal);
Fido2Lib.addExtension("test", genSpy, fn, fn); mc.enableExtension("test"); return mc.attestationOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test); assert.strictEqual(opts.extensions.test, extVal); }); });
it("calls all generators", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.enableExtension("test2"); return mc.attestationOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); }); });
it("calls all enabled generators", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.disableExtension("test2"); return mc.attestationOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isUndefined(opts.extensions.test2); }); });
it("passes through default options", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; const extOpt1 = { foo: "bar", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; const extOpt2 = null; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.setExtensionOptions("test1", extOpt1); mc.enableExtension("test2"); mc.setExtensionOptions("test2", extOpt2); return mc.attestationOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); assert.isTrue(genSpy1.calledWithExactly("test1", "attestation", extOpt1)); assert.isTrue(genSpy2.calledWithExactly("test2", "attestation", extOpt2)); }); });
it("passes through passed-in options", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; const extOpt1 = { foo: "bar", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; const extOpt2 = null; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.enableExtension("test2"); return mc.attestationOptions({ extensionOptions: { test1: extOpt1, test2: extOpt2, }, }) .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); assert.isTrue(genSpy1.calledWithExactly("test1", "attestation", extOpt1)); assert.isTrue(genSpy2.calledWithExactly("test2", "attestation", extOpt2)); }); }); });
describe("assertionOptions", function() { let mc; function fn() {} beforeEach(function() { mc = new Fido2Lib(); });
it("calls generator", function() { const genSpy = sinon.stub(); const extVal = { beer: "good", }; genSpy.returns(extVal);
Fido2Lib.addExtension("test", genSpy, fn, fn); mc.enableExtension("test"); return mc.assertionOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test); assert.strictEqual(opts.extensions.test, extVal); }); });
it("calls all generators", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.enableExtension("test2"); return mc.assertionOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); }); });
it("calls all enabled generators", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.disableExtension("test2"); return mc.assertionOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isUndefined(opts.extensions.test2); }); });
it("passes through default options", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; const extOpt1 = { foo: "bar", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; const extOpt2 = null; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.setExtensionOptions("test1", extOpt1); mc.enableExtension("test2"); mc.setExtensionOptions("test2", extOpt2); return mc.assertionOptions() .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); assert.isTrue(genSpy1.calledWithExactly("test1", "assertion", extOpt1)); assert.isTrue(genSpy2.calledWithExactly("test2", "assertion", extOpt2)); }); });
it("passes through passed-in options", function() { const genSpy1 = sinon.stub(); const extVal1 = { beer: "good", }; const extOpt1 = { foo: "bar", }; genSpy1.returns(extVal1); const genSpy2 = sinon.stub(); const extVal2 = false; const extOpt2 = null; genSpy2.returns(extVal2);
Fido2Lib.addExtension("test1", genSpy1, fn, fn); Fido2Lib.addExtension("test2", genSpy2, fn, fn); mc.enableExtension("test1"); mc.enableExtension("test2"); return mc.assertionOptions({ extensionOptions: { test1: extOpt1, test2: extOpt2, }, }) .then((opts) => { assert.isObject(opts.extensions); assert.isObject(opts.extensions.test1); assert.strictEqual(opts.extensions.test1, extVal1); assert.isFalse(opts.extensions.test2); assert.isTrue(genSpy1.calledWithExactly("test1", "assertion", extOpt1)); assert.isTrue(genSpy2.calledWithExactly("test2", "assertion", extOpt2)); }); }); });});