Skip to main content
Module

x/fido2/lib/response.js

A node.js library for performing FIDO 2.0 / WebAuthn server functionality
Go to Latest
File
import * as validator from "./validator.js";import { parseAuthnrAssertionResponse, parseAuthnrAttestationResponse, parseClientResponse, parseExpectations} from "./parser.js";
const lockSym = Symbol();
/** * The base class of {@link Fido2AttestationResult} and {@link Fido2AssertionResult} * @property {Map} authnrData Authenticator data that was parsed and validated * @property {Map} clientData Client data that was parsed and validated * @property {Map} expectations The expectations that were used to validate the result * @property {Object} request The request that was validated * @property {Map} audit A collection of audit information, such as useful warnings and information. May be useful for risk engines or for debugging. * @property {Boolean} audit.validExpectations Whether the expectations that were provided were complete and valid * @property {Boolean} audit.validRequest Whether the request message was complete and valid * @property {Boolean} audit.complete Whether all fields in the result have been validated * @property {Set} audit.journal A list of the fields that were validated * @property {Map} audit.warning A set of warnings that were generated while validating the result * @property {Map} audit.info A set of informational fields that were generated while validating the result. Includes any x509 extensions of the attestation certificate during registration, and whether the key supports a rollback counter during authentication. */class Fido2Result { constructor(sym) { if (sym !== lockSym) { throw new Error("Do not create with 'new' operator. Call 'Fido2AttestationResult.create()' or 'Fido2AssertionResult.create()' instead."); }
validator.attach(this); }
parse() { // TODO: id this.clientData = parseClientResponse(this.request); }
async validate() { // clientData, except type await this.validateRawClientDataJson(); await this.validateOrigin(); await this.validateChallenge(); await this.validateTokenBinding(); await this.validateId();
// authenticatorData, minus attestation await this.validateRawAuthnrData(); await this.validateRpIdHash(); await this.validateFlags(); await this.validateExtensions(); }
async create(req, exp) { if (typeof req !== "object") { throw new TypeError("expected 'request' to be object, got: " + typeof req); }
if (typeof exp !== "object") { throw new TypeError("expected 'expectations' to be object, got: " + typeof exp); }
this.expectations = parseExpectations(exp); this.request = req;
// validate that input expectations and request are complete and in the right format await this.validateExpectations();
// parse and validate all the request fields (CBOR, etc.) await this.parse(); await this.validate();
// ensure the parsing and validation went well await this.validateAudit();
return this; }}
/** * A validated attesetation result * @extends {Fido2Result} */class Fido2AttestationResult extends Fido2Result { constructor(sym) { super(sym);
this.requiredExpectations = new Set([ "origin", "challenge", "flags", ]); this.optionalExpectations = new Set([ "rpId", ]); }
async parse() { this.validateCreateRequest(); await super.parse(); this.authnrData = await parseAuthnrAttestationResponse(this.request); }
async validate() { await this.validateCreateType(); await this.validateAaguid(); await this.validatePublicKey(); await super.validate(); await this.validateAttestation(); await this.validateInitialCounter(); await this.validateCredId(); await this.validateTransports(); }
static async create(req, exp) { return await (new Fido2AttestationResult(lockSym)).create(req, exp); }}
/** * A validated assertion result * @extends {Fido2Result} */class Fido2AssertionResult extends Fido2Result { constructor(sym) { super(sym); this.requiredExpectations = new Set([ "origin", "challenge", "flags", "prevCounter", "publicKey", "userHandle", ]); this.optionalExpectations = new Set([ "rpId", "allowCredentials", ]); }
async parse() { this.validateAssertionResponse(); await super.parse(); this.authnrData = await parseAuthnrAssertionResponse(this.request); }
async validate() { await this.validateGetType(); await super.validate(); await this.validateAssertionSignature(); await this.validateUserHandle(); await this.validateCounter(); }
static create(req, exp) { return new Fido2AssertionResult(lockSym).create(req, exp); }}
export { Fido2Result, Fido2AttestationResult, Fido2AssertionResult};