feat: tweaks to src, use new classes and enums

This commit is contained in:
Yarmo Mackenbach 2023-07-09 12:03:25 +02:00
parent 149ac6f71e
commit 00d646e2b2
No known key found for this signature in database
GPG key ID: 3C57D093219103A3
6 changed files with 130 additions and 47 deletions

View file

@ -19,6 +19,7 @@ import { base32, base64url } from 'rfc4648'
import { Claim } from './claim.js'
import { Persona } from './persona.js'
import { Profile } from './profile.js'
import { ProfileType } from './enums.js'
const SupportedCryptoAlg = ['EdDSA', 'ES256', 'ES256K', 'ES384', 'ES512']
@ -129,9 +130,12 @@ export async function parseProfileJws (profileJws, uri) {
const profileClaimsParsed = profileClaims.map(x => new Claim(x, uri))
const pe = new Persona(profileName, profileDescription || '', profileClaimsParsed)
const pr = new Profile([pe])
pr.primaryPersona = 0
const pe = new Persona(profileName, profileClaimsParsed)
if (profileDescription) {
pe.setDescription(profileDescription)
}
const pr = new Profile(ProfileType.ASP, uri, [pe])
return pr
}

View file

@ -75,9 +75,9 @@ export const EntityEncodingFormat = {
* @readonly
* @enum {string}
*/
export const ProofAccess = {
export const ProofAccessRestriction = {
/** Any HTTP request will work */
GENERIC: 'generic',
NONE: 'none',
/** CORS requests are denied */
NOCORS: 'nocors',
/** HTTP requests must contain API or access tokens */
@ -127,13 +127,72 @@ export const ClaimRelation = {
/**
* Status of the Claim instance
* @readonly
* @enum {string}
* @enum {number}
*/
export const ClaimStatus = {
/** Claim has been initialized */
INIT: 'init',
INIT: 100,
/** Claim has matched its URI to candidate claim definitions */
MATCHED: 'matched',
/** Claim has verified one or multiple candidate claim definitions */
VERIFIED: 'verified'
MATCHED: 101,
/** Claim was successfully verified */
VERIFIED: 200,
/** Claim was successfully verified using proxied data */
VERIFIED_VIA_PROXY: 201,
/** Unknown matching error */
MATCHING_ERROR: 300,
/** No matched service providers */
NO_MATCHES: 301,
/** Unknown matching error */
VERIFICATION_ERROR: 400,
/** No proof found in data returned by service providers */
NO_PROOF_FOUND: 401
}
/**
* Profile type
* @readonly
* @enum {string}
*/
export const ProfileType = {
/** ASP profile */
ASP: 'asp',
/** OpenPGP profile */
OPENPGP: 'openpgp'
}
/**
* Public key type
* @readonly
* @enum {string}
*/
export const PublicKeyType = {
EDDSA: 'eddsa',
ES256: 'es256',
OPENPGP: 'openpgp',
NONE: 'none'
}
/**
* Public key format
* @readonly
* @enum {string}
*/
export const PublicKeyEncoding = {
PEM: 'pem',
JWK: 'jwk',
ARMORED_PGP: 'armored_pgp',
NONE: 'none'
}
/**
* Method to fetch the public key
* @readonly
* @enum {string}
*/
export const PublicKeyFetchMethod = {
ASPE: 'aspe',
HKP: 'hkp',
WKD: 'wkd',
HTTP: 'http',
NONE: 'none'
}

View file

@ -17,6 +17,7 @@ export { Profile } from './profile.js'
export { Persona } from './persona.js'
export { Claim } from './claim.js'
export { ServiceProvider } from './serviceProvider.js'
export * as ServiceProviderDefinitions from './serviceProviders/index.js'
export * as proofs from './proofs.js'
export * as openpgp from './openpgp.js'
export * as asp from './asp.js'

View file

@ -16,7 +16,7 @@ limitations under the License.
import { isNode } from 'browser-or-node'
import * as fetcher from './fetcher/index.js'
import { generateProxyURL } from './utils.js'
import { Fetcher, ProxyPolicy, ProofAccess } from './enums.js'
import { ProxyPolicy, ProofAccessRestriction } from './enums.js'
/**
* @module proofs
@ -29,20 +29,11 @@ import { Fetcher, ProxyPolicy, ProofAccess } from './enums.js'
* choose the right approach to fetch the proof. An error will be thrown if no
* approach is possible.
* @async
* @param {object} data - Data from a claim definition
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
export async function fetch (data, opts) {
switch (data.proof.request.fetcher) {
case Fetcher.HTTP:
data.proof.request.data.format = data.proof.request.format
break
default:
break
}
if (isNode) {
return handleNodeRequests(data, opts)
}
@ -50,6 +41,11 @@ export async function fetch (data, opts) {
return handleBrowserRequests(data, opts)
}
/**
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
const handleBrowserRequests = (data, opts) => {
switch (opts.proxy.policy) {
case ProxyPolicy.ALWAYS:
@ -57,11 +53,11 @@ const handleBrowserRequests = (data, opts) => {
case ProxyPolicy.NEVER:
switch (data.proof.request.access) {
case ProofAccess.GENERIC:
case ProofAccess.GRANTED:
case ProofAccessRestriction.NONE:
case ProofAccessRestriction.GRANTED:
return createDefaultRequestPromise(data, opts)
case ProofAccess.NOCORS:
case ProofAccess.SERVER:
case ProofAccessRestriction.NOCORS:
case ProofAccessRestriction.SERVER:
throw new Error(
'Impossible to fetch proof (bad combination of service access and proxy policy)'
)
@ -71,13 +67,13 @@ const handleBrowserRequests = (data, opts) => {
case ProxyPolicy.ADAPTIVE:
switch (data.proof.request.access) {
case ProofAccess.GENERIC:
case ProofAccessRestriction.NONE:
return createFallbackRequestPromise(data, opts)
case ProofAccess.NOCORS:
case ProofAccessRestriction.NOCORS:
return createProxyRequestPromise(data, opts)
case ProofAccess.GRANTED:
case ProofAccessRestriction.GRANTED:
return createFallbackRequestPromise(data, opts)
case ProofAccess.SERVER:
case ProofAccessRestriction.SERVER:
return createProxyRequestPromise(data, opts)
default:
throw new Error('Invalid proof access value')
@ -88,6 +84,11 @@ const handleBrowserRequests = (data, opts) => {
}
}
/**
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
const handleNodeRequests = (data, opts) => {
switch (opts.proxy.policy) {
case ProxyPolicy.ALWAYS:
@ -104,13 +105,21 @@ const handleNodeRequests = (data, opts) => {
}
}
/**
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
const createDefaultRequestPromise = (data, opts) => {
return new Promise((resolve, reject) => {
fetcher[data.proof.request.fetcher]
if (!(data.proof.request.protocol in fetcher)) {
reject(new Error(`fetcher for ${data.proof.request.protocol} not found`))
}
fetcher[data.proof.request.protocol]
.fn(data.proof.request.data, opts)
.then((res) => {
return resolve({
fetcher: data.proof.request.fetcher,
protocol: data.proof.request.protocol,
data,
viaProxy: false,
result: res
@ -122,12 +131,17 @@ const createDefaultRequestPromise = (data, opts) => {
})
}
/**
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
const createProxyRequestPromise = (data, opts) => {
return new Promise((resolve, reject) => {
let proxyUrl
try {
proxyUrl = generateProxyURL(
data.proof.request.fetcher,
data.proof.request.protocol,
data.proof.request.data,
opts
)
@ -138,13 +152,13 @@ const createProxyRequestPromise = (data, opts) => {
const requestData = {
url: proxyUrl,
format: data.proof.request.format,
fetcherTimeout: fetcher[data.proof.request.fetcher].timeout
fetcherTimeout: fetcher[data.proof.request.protocol].timeout
}
fetcher.http
.fn(requestData, opts)
.then((res) => {
return resolve({
fetcher: 'http',
protocol: 'http',
data,
viaProxy: true,
result: res
@ -156,6 +170,11 @@ const createProxyRequestPromise = (data, opts) => {
})
}
/**
* @param {import('./serviceProvider.js').ServiceProvider} data - Data from a claim definition
* @param {object} opts - Options to enable the request
* @returns {Promise<object|string>}
*/
const createFallbackRequestPromise = (data, opts) => {
return new Promise((resolve, reject) => {
createDefaultRequestPromise(data, opts)

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import { readCleartextMessage, verify } from 'openpgp'
import { Claim } from './claim.js'
import { fetchURI } from './keys.js'
import { fetchURI } from './openpgp.js'
/**
* @module signatures
@ -89,7 +89,7 @@ export async function process (signature) {
if (sigKeys.length > 0) {
try {
result.key.uri = sigKeys[0]
result.key.data = await fetchURI(result.key.uri)
result.key.data = (await fetchURI(result.key.uri)).publicKey.key
result.key.fetchMethod = result.key.uri.split(':')[0]
} catch (e) {}
}
@ -97,7 +97,7 @@ export async function process (signature) {
if (!result.key.data && signersUserID) {
try {
result.key.uri = `wkd:${signersUserID}`
result.key.data = await fetchURI(result.key.uri)
result.key.data = (await fetchURI(result.key.uri)).publicKey.key
result.key.fetchMethod = 'wkd'
} catch (e) {}
}
@ -106,7 +106,7 @@ export async function process (signature) {
try {
const match = preferredKeyServer.match(/^(.*:\/\/)?([^/]*)(?:\/)?$/i)
result.key.uri = `hkp:${match[2]}:${issuerKeyID || signersUserID}`
result.key.data = await fetchURI(result.key.uri)
result.key.data = (await fetchURI(result.key.uri)).publicKey.key
result.key.fetchMethod = 'hkp'
} catch (e) {
throw new Error('Public key not found')

View file

@ -176,7 +176,7 @@ const containsProof = async (data, params) => {
/**
* @function
* @param {any} proofData
* @param {string} checkPath
* @param {string[]} checkPath
* @param {object} params
* @param {string} params.target
* @param {string} params.claimFormat
@ -232,7 +232,7 @@ 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 {object} claimData - The claim data
* @param {import('./serviceProvider.js').ServiceProvider} claimData - The claim data
* @param {string} fingerprint - The fingerprint
* @returns {Promise<object>}
*/
@ -243,10 +243,10 @@ export async function run (proofData, claimData, fingerprint) {
errors: []
}
switch (claimData.proof.request.format) {
switch (claimData.proof.response.format) {
case ProofFormat.JSON:
for (let index = 0; index < claimData.claim.length; index++) {
const claimMethod = claimData.claim[index]
for (let index = 0; index < claimData.proof.target.length; index++) {
const claimMethod = claimData.proof.target[index]
try {
res.result = res.result || await runJSON(
proofData,
@ -265,8 +265,8 @@ export async function run (proofData, claimData, fingerprint) {
res.completed = true
break
case ProofFormat.TEXT:
for (let index = 0; index < claimData.claim.length; index++) {
const claimMethod = claimData.claim[index]
for (let index = 0; index < claimData.proof.target.length; index++) {
const claimMethod = claimData.proof.target[index]
try {
res.result = res.result || await containsProof(
proofData,