extensionDataHex: defaultTo()

in fido.js [124:211]


            extensionDataHex: defaultTo(authenticatorData.extensionDataHex, "No extension data"),
            clientDataJSONHex: "none",
            signatureHex: "none",
            userHandleHex: "none"
        }
    };

    await storage.Credentials.create(credential);

    return credential;
};

/**
 * Verifies a FIDO assertion
 * @param {String} uid user id
 * @param {EncodedAssertionResponse} assertion AuthenticatorAssertionResponse received from client
 * @return {Promise<Credential>} credential object that the assertion verified
 */
fido.verifyAssertion = async (uid, assertion) => {
    // https://w3c.github.io/webauthn/#verifying-assertion

    // Step 1 and 2 are skipped because this is a sample app

    // Step 3: Using credential’s id attribute look up the corresponding
    // credential public key.
    /** @typeof {Credential} */
    const credential = await storage.Credentials.findOne({
        uid: uid,
        id: assertion.id
    });


    // Step 4: Let cData, authData and sig denote the value of credential’s
    // response's clientDataJSON, authenticatorData, and signature respectively
    const cData = assertion.clientDataJSON;
    const authData = Buffer.from(assertion.authenticatorData, 'base64');
    const sig = Buffer.from(assertion.signature, 'base64');

    // Step 5 and 6: Let C be the decoded client data claimed by the signature.
    let C;
    try {
        C = JSON.parse(cData);
    } catch (e) {
        throw new Error("clientDataJSON could not be parsed");
    }
    //Step 7-10: Verify client data
    validateClientData(C, uid, "webauthn.get");

    //Parse authenticator data used for the next few steps
    const authenticatorData = parseAuthenticatorData(authData);

    //Step 11: Verify that the rpIdHash in authData is the SHA-256 hash of the
    //RP ID expected by the Relying Party.
    const expectedRpId = defaultTo(assertion.metadata.rpId, hostname)
    if (!authenticatorData.rpIdHash.equals(sha256(expectedRpId))) {
        throw new Error("RPID hash does not match expected value: sha256(" + expectedRpId + ")");
    }

    //Step 12: Verify that the User Present bit of the flags in authData is set
    if ((authenticatorData.flags & 0b00000001) == 0) {
        throw new Error("User Present bit was not set.");
    }

    //Step 13-14 are skipped because this is a test site

    //Step 15: Let hash be the result of computing a hash over the cData using
    //SHA-256.
    const hash = sha256(cData);

    //Step 16: Using the credential public key looked up in step 3, verify
    //that sig is a valid signature over the binary concatenation of authData
    //and hash.
    const publicKey = JSON.parse(credential.creationData.publicKey);
    const publicKeyEd = publicKey.key;

    var verify;
    if (publicKey.kty === "RSA")
    {
        verify = crypto.createVerify('RSA-SHA256');
        verify.update(authData);
        verify.update(hash);
        if (!verify.verify(jwkToPem(publicKey), sig))
            throw new Error("Could not verify signature");
    }
    else if (publicKey.kty === "EC")
    {
        if (publicKey.crv === "P-256")
        {