diff --git a/src/asp.js b/src/asp.js index 2c05289..655163e 100644 --- a/src/asp.js +++ b/src/asp.js @@ -13,8 +13,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import axios from 'axios' +import axios, * as axiosMod from 'axios' import { decodeProtectedHeader, importJWK, compactVerify, calculateJwkThumbprint } from 'jose' +import * as joseMod from 'jose' import { base32, base64url } from 'rfc4648' import { Claim } from './claim.js' import { Persona } from './persona.js' @@ -57,12 +58,12 @@ export async function fetchASPE (uri) { responseType: 'text' } ) - .then((/** @type {import('axios').AxiosResponse} */ response) => { + .then((/** @type {axiosMod.AxiosResponse} */ response) => { if (response.status === 200) { return response } }) - .then((/** @type {import('axios').AxiosResponse} */ response) => response.data) + .then((/** @type {axiosMod.AxiosResponse} */ response) => response.data) } catch (e) { throw new Error(`Error fetching Keybase key: ${e.message}`) } @@ -171,7 +172,7 @@ export async function parseProfileJws (profileJws, uri) { /** * Compute the fingerprint for JWK keys * @function - * @param {import('jose').JWK} key + * @param {joseMod.JWK} key * @returns {Promise} */ export async function computeJwkFingerprint (key) { diff --git a/src/claim.js b/src/claim.js index b822c3d..fe3e0f2 100644 --- a/src/claim.js +++ b/src/claim.js @@ -18,6 +18,7 @@ import { isUri } from 'valid-url' import mergeOptions from 'merge-options' import { fetch } from './proofs.js' import { run } from './verifications.js' +import * as verificationsMod from './verifications.js' import { list, data as _data } from './serviceProviders/index.js' import { opts as _opts } from './defaults.js' import { ClaimStatus } from './enums.js' @@ -71,7 +72,7 @@ export class Claim { */ this._status = ClaimStatus.INIT /** - * @type {import('./serviceProvider.js').ServiceProvider[]} + * @type {ServiceProvider[]} */ this._matches = [] } @@ -245,6 +246,7 @@ export class Claim { let claimData = this._matches[index] + /** @type {verificationsMod.VerificationResult} */ let verificationResult = null let proofData = null let proofFetchError @@ -286,7 +288,7 @@ export class Claim { verificationResult = verificationResult || { result: false, completed: true, - proof: {}, + proof: null, errors: [proofFetchError] } } diff --git a/src/openpgp.js b/src/openpgp.js index 40f7bdc..5ea0392 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import axios from 'axios' +import axios, * as axiosMod from 'axios' import { isUri } from 'valid-url' import { readKey, PublicKey } from 'openpgp' import HKP from '@openpgp/hkp-client' @@ -129,12 +129,12 @@ export async function fetchKeybase (username, fingerprint) { responseType: 'text' } ) - .then((/** @type {import('axios').AxiosResponse} */ response) => { + .then((/** @type {axiosMod.AxiosResponse} */ response) => { if (response.status === 200) { return response } }) - .then((/** @type {import('axios').AxiosResponse} */ response) => response.data) + .then((/** @type {axiosMod.AxiosResponse} */ response) => response.data) } catch (e) { throw new Error(`Error fetching Keybase key: ${e.message}`) } diff --git a/src/persona.js b/src/persona.js index cff55de..5c14a95 100644 --- a/src/persona.js +++ b/src/persona.js @@ -27,7 +27,7 @@ import { Claim } from './claim.js' export class Persona { /** * @param {string} name - * @param {import('./claim.js').Claim[]} claims + * @param {Claim[]} claims */ constructor (name, claims) { /** @@ -68,7 +68,7 @@ export class Persona { this.themeColor = null /** * List of identity claims - * @type {import('./claim.js').Claim[]} + * @type {Claim[]} * @public */ this.claims = claims @@ -145,7 +145,7 @@ export class Persona { /** * @function - * @param {import('./claim.js').Claim} claim + * @param {Claim} claim */ addClaim (claim) { this.claims.push(claim) diff --git a/src/profile.js b/src/profile.js index 698d09c..e4906a8 100644 --- a/src/profile.js +++ b/src/profile.js @@ -13,13 +13,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { PublicKeyFetchMethod, PublicKeyEncoding, PublicKeyType } from './enums.js' +import { PublicKey } from 'openpgp' +import * as joseMod from 'jose' +import { PublicKeyFetchMethod, PublicKeyEncoding, PublicKeyType, ProfileType } from './enums.js' import { Persona } from './persona.js' +/** + * The online verifier instance of identity profiles like Keyoxide's web interface + * @typedef {Object} ProfileVerifier + * @property {string} name - Name of the profile verifier + * @property {string} url - URL to the profile verifier + */ + /** * A profile of personas with identity claims * @function - * @param {Array} personas + * @param {Array} personas * @public * @example * const claim = Claim('https://alice.tld', '123'); @@ -30,9 +39,9 @@ export class Profile { /** * Create a new profile * @function - * @param {import('./enums.js').ProfileType} profileType + * @param {ProfileType} profileType * @param {string} identifier - * @param {Array} personas + * @param {Array} personas * @public */ constructor (profileType, identifier, personas) { @@ -44,7 +53,7 @@ export class Profile { this.profileVersion = 2 /** * Profile version - * @type {import('./enums.js').ProfileType} + * @type {ProfileType} * @public */ this.profileType = profileType @@ -56,7 +65,7 @@ export class Profile { this.identifier = identifier /** * List of personas - * @type {Array} + * @type {Array} * @public */ this.personas = personas || [] @@ -98,7 +107,7 @@ export class Profile { encodedKey: null, /** * The raw cryptographic key as object (to be removed during toJSON()) - * @type {import('openpgp').PublicKey | import('jose').JWK | null} + * @type {PublicKey | joseMod.JWK | null} * @public */ key: null, @@ -130,7 +139,7 @@ export class Profile { } /** * List of verifier URLs - * @type {{name: string, url: string}[]} + * @type {ProfileVerifier[]} * @public */ this.verifiers = [] diff --git a/src/proofs.js b/src/proofs.js index b4aa450..b77bc49 100644 --- a/src/proofs.js +++ b/src/proofs.js @@ -17,6 +17,7 @@ import { isNode } from 'browser-or-node' import { fetcher } from './index.js' import { generateProxyURL } from './utils.js' import { ProxyPolicy, ProofAccessRestriction } from './enums.js' +import { ServiceProvider } from './serviceProvider.js' /** * @module proofs @@ -29,7 +30,7 @@ import { ProxyPolicy, ProofAccessRestriction } from './enums.js' * choose the right approach to fetch the proof. An error will be thrown if no * approach is possible. * @async - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ @@ -42,7 +43,7 @@ export async function fetch (data, opts) { } /** - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ @@ -85,7 +86,7 @@ const handleBrowserRequests = (data, opts) => { } /** - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ @@ -106,7 +107,7 @@ const handleNodeRequests = (data, opts) => { } /** - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ @@ -132,7 +133,7 @@ const createDefaultRequestPromise = (data, opts) => { } /** - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ @@ -171,7 +172,7 @@ const createProxyRequestPromise = (data, opts) => { } /** - * @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition + * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request * @returns {Promise} */ diff --git a/src/serviceProvider.js b/src/serviceProvider.js index 91e1835..aca19f1 100644 --- a/src/serviceProvider.js +++ b/src/serviceProvider.js @@ -13,6 +13,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +import { ClaimFormat, ClaimRelation, EntityEncodingFormat, ProofAccessRestriction, ProofFormat } from "./enums" + +/** + * The method to find the proof inside the response data + * @typedef {Object} ProofTarget + * @property {ClaimFormat} format - How the response data is formatted + * @property {EntityEncodingFormat} encoding - How the response data is encoded + * @property {ClaimRelation} relation - How the proof is related to the response data + * @property {string[]} path - Path to the proof inside the response data object + */ + /** * A service provider matched to an identity claim * @class @@ -104,7 +115,7 @@ export class ServiceProvider { fetcher: spObj.proof.request.fetcher, /** * Type of access restriction - * @type {import('./enums.js').ProofAccessRestriction} + * @type {ProofAccessRestriction} */ accessRestriction: spObj.proof.request.accessRestriction, /** @@ -120,13 +131,13 @@ export class ServiceProvider { response: { /** * Expected format of the proof - * @type {import('./enums.js').ProofFormat} + * @type {ProofFormat} */ format: spObj.proof.response.format }, /** * Details about the target located in the response - * @type {{format: import('./enums.js').ClaimFormat, encoding: import('./enums.js').EntityEncodingFormat, relation: import('./enums.js').ClaimRelation, path: string[]}[]} + * @type {ProofTarget[]} */ target: spObj.proof.target } diff --git a/src/signatures.js b/src/signatures.js index 467494b..114dceb 100644 --- a/src/signatures.js +++ b/src/signatures.js @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { readCleartextMessage, verify } from 'openpgp' +import { CleartextMessage, PublicKey, readCleartextMessage, verify } from 'openpgp' import { Claim } from './claim.js' import { fetchURI } from './openpgp.js' import { Profile } from './profile.js' @@ -28,10 +28,10 @@ import { Persona } from './persona.js' * Extract the profile from a signature and fetch the associated key * @async * @param {string} signature - The plaintext signature to parse - * @returns {Promise} + * @returns {Promise} */ export async function parse (signature) { - /** @type {import('openpgp').CleartextMessage} */ + /** @type {CleartextMessage} */ let sigData // Read the signature @@ -84,7 +84,7 @@ export async function parse (signature) { if (sigKeys.length > 0) { try { obtainedKey.query = sigKeys[0] - /** @type {import('openpgp').PublicKey} */ + /** @type {PublicKey} */ obtainedKey.data = (await fetchURI(obtainedKey.query)).publicKey.key obtainedKey.method = obtainedKey.query.split(':')[0] } catch (e) {} diff --git a/src/verifications.js b/src/verifications.js index f54d04c..f7f329a 100644 --- a/src/verifications.js +++ b/src/verifications.js @@ -17,20 +17,42 @@ import { generateClaim, getUriFromString } from './utils.js' import { ClaimFormat, EntityEncodingFormat, ClaimRelation, ProofFormat } from './enums.js' import { bcryptVerify, argon2Verify } from 'hash-wasm' import { decodeHTML, decodeXML } from 'entities' +import { ServiceProvider } from './serviceProvider.js' /** * @module verifications * @ignore */ +/** + * Parameters needed to perform the proof verification + * @typedef {object} VerificationParams + * @property {string} target + * @property {ClaimFormat} claimFormat + * @property {EntityEncodingFormat} proofEncodingFormat + * @property {ClaimRelation} [claimRelation] + */ + +/** + * Result of the proof verification + * @typedef {Object} VerificationResult + * @property {boolean} result + * @property {boolean} completed + * @property {VerificationResultProof} [proof] + * @property {any[]} errors + */ + +/** + * Information about the proof in the proof verification result + * @typedef {Object} VerificationResultProof + * @property {string} fetcher + * @property {boolean} viaProxy + */ + /** * @function * @param {string} data - * @param {object} params - * @param {string} params.target - * @param {string} params.claimFormat - * @param {string} params.proofEncodingFormat - * @param {string} [params.claimRelation] + * @param {VerificationParams} params * @returns {Promise} */ const containsProof = async (data, params) => { @@ -218,11 +240,7 @@ const containsProof = async (data, params) => { * @function * @param {any} proofData * @param {string[]} checkPath - * @param {object} params - * @param {string} params.target - * @param {string} params.claimFormat - * @param {string} params.proofEncodingFormat - * @param {string} [params.claimRelation] + * @param {VerificationParams} params * @returns {Promise} */ const runJSON = async (proofData, checkPath, params) => { @@ -272,12 +290,13 @@ const runJSON = async (proofData, checkPath, params) => { /** * Run the verification by finding the formatted fingerprint in the proof * @async - * @param {object} proofData - The proof data - * @param {import('./serviceProvider.js').ServiceProvider} claimData - The claim data - * @param {string} fingerprint - The fingerprint - * @returns {Promise} + * @param {object} proofData - The proof data + * @param {ServiceProvider} claimData - The claim data + * @param {string} fingerprint - The fingerprint + * @returns {Promise} */ export async function run (proofData, claimData, fingerprint) { + /** @type {VerificationResult} */ const res = { result: false, completed: false,