@animo-id/eudi-wallet-functionality 0.0.0-alpha-20250917090914 → 0.0.0-alpha-20260108162340
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +858 -11
- package/dist/index.mjs +403 -201
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -20
- package/dist/index.d.ts +0 -15
- package/dist/index.js +0 -244
- package/dist/index.js.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/verifyOpenid4VpAuthorizationRequest.ts","../src/isDcqlQueryEqualOrSubset.ts"],"sourcesContent":["import { type AgentContext, type DcqlQuery, JwsService, Jwt, X509Certificate } from '@credo-ts/core'\nimport type { OpenId4VpResolvedAuthorizationRequest } from '@credo-ts/openid4vc'\nimport z from 'zod'\nimport { isDcqlQueryEqualOrSubset } from './isDcqlQueryEqualOrSubset'\n\nexport type VerifyAuthorizationRequestOptions = {\n resolvedAuthorizationRequest: OpenId4VpResolvedAuthorizationRequest\n trustedCertificates?: Array<string>\n allowUntrustedSigned?: boolean\n}\n\nexport const verifyOpenid4VpAuthorizationRequest = async (\n agentContext: AgentContext,\n {\n resolvedAuthorizationRequest: { authorizationRequestPayload, signedAuthorizationRequest, dcql },\n trustedCertificates,\n allowUntrustedSigned,\n }: VerifyAuthorizationRequestOptions\n) => {\n const results = []\n if (!authorizationRequestPayload.verifier_attestations) return\n for (const va of authorizationRequestPayload.verifier_attestations) {\n // Here we verify it as a registration certificate according to\n // https://bmi.usercontent.opencode.de/eudi-wallet/eidas-2.0-architekturkonzept/flows/Wallet-Relying-Party-Authentication/#registration-certificate\n if (va.format === 'jwt') {\n if (typeof va.data !== 'string') {\n throw new Error('Only inline JWTs are supported')\n }\n\n const jwsService = agentContext.dependencyManager.resolve(JwsService)\n\n let isValidButUntrusted = false\n let isValidAndTrusted = false\n\n const jwt = Jwt.fromSerializedJwt(va.data)\n\n try {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates,\n })\n isValidAndTrusted = isValid\n } catch {\n if (allowUntrustedSigned) {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates: jwt.header.x5c ?? [],\n })\n isValidButUntrusted = isValid\n }\n }\n\n if (jwt.header.typ !== 'rc-rp+jwt') {\n throw new Error(`only 'rc-rp+jwt' is supported as header typ. Request included: ${jwt.header.typ}`)\n }\n\n if (!signedAuthorizationRequest) {\n throw new Error('Request must be signed for the registration certificate')\n }\n\n if (signedAuthorizationRequest.signer.method !== 'x5c') {\n throw new Error('x5c is only supported for registration certificate')\n }\n\n const registrationCertificateHeaderSchema = z\n .object({\n typ: z.literal('rc-rp+jwt'),\n alg: z.string(),\n // sprin-d did not define this\n x5u: z.string().url().optional(),\n // sprin-d did not define this\n 'x5t#s256': z.string().optional(),\n })\n .passthrough()\n\n // TODO: does not support intermediaries\n const registrationCertificatePayloadSchema = z\n .object({\n credentials: z.array(\n z.object({\n format: z.string(),\n multiple: z.boolean().default(false),\n meta: z\n .object({\n vct_values: z.array(z.string()).optional(),\n doctype_value: z.string().optional(),\n })\n .optional(),\n trusted_authorities: z\n .array(z.object({ type: z.string(), values: z.array(z.string()) }))\n .nonempty()\n .optional(),\n require_cryptographic_holder_binding: z.boolean().default(true),\n claims: z\n .array(\n z.object({\n id: z.string().optional(),\n path: z.array(z.string()).nonempty().nonempty(),\n values: z.array(z.number().or(z.boolean())).optional(),\n })\n )\n .nonempty()\n .optional(),\n claim_sets: z.array(z.array(z.string())).nonempty().optional(),\n })\n ),\n contact: z.object({\n website: z.string().url(),\n 'e-mail': z.string().email(),\n phone: z.string(),\n }),\n sub: z.string(),\n // Should be service\n services: z.array(z.object({ lang: z.string(), name: z.string() })),\n public_body: z.boolean().default(false),\n entitlements: z.array(z.any()),\n provided_attestations: z\n .array(\n z.object({\n format: z.string(),\n meta: z.any(),\n })\n )\n .optional(),\n privacy_policy: z.string().url(),\n iat: z.number().optional(),\n exp: z.number().optional(),\n purpose: z\n .array(\n z.object({\n locale: z.string().optional(),\n lang: z.string().optional(),\n name: z.string(),\n })\n )\n .optional(),\n status: z.any(),\n })\n .passthrough()\n\n registrationCertificateHeaderSchema.parse(jwt.header)\n const parsedPayload = registrationCertificatePayloadSchema.parse(jwt.payload.toJson())\n\n const [rpCertEncoded] = signedAuthorizationRequest.signer.x5c\n const rpCert = X509Certificate.fromEncodedCertificate(rpCertEncoded)\n\n if (rpCert.subject !== parsedPayload.sub) {\n throw new Error(\n `Subject in the certificate of the auth request: '${rpCert.subject}' is not equal to the subject of the registration certificate: '${parsedPayload.sub}'`\n )\n }\n\n if (parsedPayload.iat && new Date().getTime() / 1000 <= parsedPayload.iat) {\n throw new Error('Issued at timestamp of the registration certificate is in the future')\n }\n\n // TODO: check the status of the registration certificate\n\n if (!dcql) {\n throw new Error('DCQL must be used when working registration certificates')\n }\n\n if (\n authorizationRequestPayload.presentation_definition ||\n authorizationRequestPayload.presentation_definition_uri\n ) {\n throw new Error('Presentation Exchange is not supported for the registration certificate')\n }\n\n const isValidDcqlQuery = isDcqlQueryEqualOrSubset(dcql.queryResult, parsedPayload as unknown as DcqlQuery)\n\n if (!isValidDcqlQuery) {\n throw new Error(\n 'DCQL query in the authorization request is not equal or a valid subset of the DCQl query provided in the registration certificate'\n )\n }\n\n results.push({ isValidButUntrusted, isValidAndTrusted, x509RegistrationCertificate: rpCert })\n } else {\n throw new Error(`only format of 'jwt' is supported`)\n }\n }\n return results\n}\n","import { type DcqlQuery, equalsIgnoreOrder, equalsWithOrder } from '@credo-ts/core'\n\nexport function isDcqlQueryEqualOrSubset(arq: DcqlQuery, rcq: DcqlQuery): boolean {\n if (rcq.credential_sets) {\n return false\n }\n\n if (rcq.credentials.some((c) => c.id)) {\n return false\n }\n\n // only sd-jwt and mdoc are supported\n if (arq.credentials.some((c) => c.format !== 'mso_mdoc' && c.format !== 'vc+sd-jwt' && c.format !== 'dc+sd-jwt')) {\n return false\n }\n\n credentialQueryLoop: for (const credentialQuery of arq.credentials) {\n const matchingRcqCredentialQueriesBasedOnFormat = rcq.credentials.filter((c) => c.format === credentialQuery.format)\n\n if (matchingRcqCredentialQueriesBasedOnFormat.length === 0) return false\n\n switch (credentialQuery.format) {\n case 'mso_mdoc': {\n const doctypeValue = credentialQuery.meta?.doctype_value\n if (!doctypeValue) return false\n if (typeof credentialQuery.meta?.doctype_value !== 'string') return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & { format: 'mso_mdoc' } =>\n !!(c.format === 'mso_mdoc' && c.meta && c.meta.doctype_value === doctypeValue)\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for mdoc, this means matching the `path[0]` (namespace) and `path[1]` (value name)\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c &&\n matchedRequest.claims?.some(\n (mrc) => 'path' in mrc && c.path[0] === mrc.path[0] && c.path[1] === mrc.path[1]\n )\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n case 'dc+sd-jwt':\n case 'vc+sd-jwt': {\n const vctValues = credentialQuery.meta?.vct_values\n if (!vctValues) return false\n if (credentialQuery.meta?.vct_values?.length === 0) return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & ({ format: 'dc+sd-jwt' } | { format: 'vc+sd-jwt' }) =>\n !!(\n (c.format === 'dc+sd-jwt' || c.format === 'vc+sd-jwt') &&\n c.meta?.vct_values &&\n equalsIgnoreOrder(c.meta.vct_values, vctValues)\n )\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for sd-jwt, this means making sure that every `path[n]` is in the registration certificate\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c && matchedRequest.claims?.some((mrc) => 'path' in mrc && equalsWithOrder(c.path, mrc.path))\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n default:\n return false\n }\n }\n\n return true\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["resolved: Partial<ResolvedTs12Metadata>","z"],"sources":["../src/error.ts","../src/validation/z-sca-attestation-ext.ts","../src/validation/z-transaction-data-common.ts","../src/validation/z-transaction-data-funke.ts","../src/validation/z-transaction-data-ts12.ts","../src/validation/z-transaction-data.ts","../src/validation/ts12.ts","../src/isDcqlQueryEqualOrSubset.ts","../src/verifyOpenid4VpAuthorizationRequest.ts"],"sourcesContent":["export class EudiWalletExtensionsError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'EudiWalletExtensionsError'\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EudiWalletExtensionsError)\n }\n }\n}\n\nexport class Ts12IntegrityError extends EudiWalletExtensionsError {\n constructor(uri: string, integrity: string) {\n super(`Invalid integrity for ${uri}, expected ${integrity}`)\n this.name = 'Ts12IntegrityError'\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, Ts12IntegrityError)\n }\n }\n}\n","import { z } from 'zod'\n\nexport const zScaTransactionDataTypeClaims = z.array(\n z.object({\n /** The path to the claim within the transaction payload. */\n path: z.array(z.string()),\n /** * [TS12 3.3.2] Visual importance.\n * 1: Prominent (Top priority)\n * 2: Main (Standard visibility)\n * 3: Supplementary (Details view)\n * 4: Omitted (Not displayed)\n */\n visualisation: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)]).default(3),\n /** [ARF Annex 4] Localised display information for the claim. */\n display: z\n .array(\n z.object({\n /** Localised name of the claim (e.g., \"Amount\"). */\n name: z.string(),\n /** [ISO639-1] Language code (e.g., \"en\"). */\n locale: z.string().optional(),\n /** [RFC2397] Resolvable or Data URL of the claim icon. */\n logo: z.string().optional(),\n })\n )\n .min(1),\n })\n)\n\nexport const zScaTransactionDataTypeUiLabels = z\n .object({\n /**\n * [REQUIRED] Label for the confirmation (consent) button.\n * Max length: 30 characters.\n */\n affirmative_action_label: z\n .array(\n z.object({\n /** [RFC5646] Language identifier (e.g., \"en\", \"fr-CA\"). */\n lang: z.string(),\n /** Localised string value. Max length: 30 chars. */\n value: z.string().max(30),\n })\n )\n .min(1),\n\n /**\n * [OPTIONAL] Label for the denial (cancel) button.\n * Max length: 30 characters.\n */\n denial_action_label: z\n .array(\n z.object({\n /** [RFC5646] Language identifier. */\n lang: z.string(),\n /** Localised string value. Max length: 30 chars. */\n value: z.string().max(30),\n })\n )\n .min(1)\n .optional(),\n\n /**\n * [OPTIONAL] Title/headline for the transaction confirmation screen.\n * Max length: 50 characters.\n */\n transaction_title: z\n .array(\n z.object({\n /** [RFC5646] Language identifier. */\n lang: z.string(),\n /** Localised string value. Max length: 50 chars. */\n value: z.string().max(50),\n })\n )\n .min(1)\n .optional(),\n\n /**\n * [OPTIONAL] Security hint to be displayed to the User.\n * Max length: 250 characters.\n */\n security_hint: z\n .array(\n z.object({\n /** [RFC5646] Language identifier. */\n lang: z.string(),\n /** Localised string value. Max length: 250 chars. */\n value: z.string().max(250),\n })\n )\n .min(1)\n .optional(),\n })\n .catchall(\n // [TS12] \"Additional UI elements identifiers MAY be defined\"\n z.array(\n z.object({\n lang: z.string(),\n value: z.string(),\n })\n )\n )\n\n/**\n * @name zScaAttestationExt\n * @version EUDI TS12 v1.0 (05 December 2025)\n * @description Defines metadata for SCA Attestations, including transaction types and UI localization.\n * @see [EUDI TS12, Section 3] for VC Type Metadata requirements.\n * @see [EUDI TS12, Section 4.1] for Metadata structure.\n */\nexport const zScaAttestationExt = z.object({\n /**\n * [TS12 Section 3] Category the attestation belongs to.\n * MUST be 'urn:eu:europa:ec:eudi:sua:sca' for SCA Attestations.\n */\n category: z.string().optional(),\n transaction_data_types: z.record(\n z.string().describe('Transaction Type URI (e.g., urn:eudi:sca:payment:1). Must be collision resistant.'),\n z.intersection(\n z.union([\n z.object({\n /** [TS12 4.1] Embedded JSON Schema string defining the payload structure. MUST NOT be used if schema_uri is present. */\n schema: z.string(),\n }),\n z.object({\n /** [TS12 4.1] URI referencing an external JSON Schema document. MUST NOT be used if schema is present. */\n schema_uri: z.url(),\n 'schema_uri#integrity': z.string().optional(),\n }),\n ]),\n z.intersection(\n z.union([\n z.object({\n /** [TS12 3.3.2] Transaction Data Claim Metadata. MUST NOT be used if claims_uri is present. */\n claims: zScaTransactionDataTypeClaims,\n }),\n z.object({\n /** [TS12 3.3.2] URI referencing an external claims metadata document. MUST NOT be used if claims is present. */\n claims_uri: z.url(),\n 'claims_uri#integrity': z.string().optional(),\n }),\n ]),\n z.union([\n z.object({\n /** [TS12 3.3.3] Localised UI element values. MUST NOT be used if ui_labels_uri is present. */\n ui_labels: zScaTransactionDataTypeUiLabels,\n }),\n z.object({\n /** [TS12 3.3.3] URI referencing external UI labels. MUST NOT be used if ui_labels is present. */\n ui_labels_uri: z.string().url(),\n 'ui_labels_uri#integrity': z.string().optional(),\n }),\n ])\n )\n )\n ),\n})\n\nexport type ZScaAttestationExt = z.infer<typeof zScaAttestationExt>\n","import { z } from 'zod'\n\n/**\n * **OpenID4VP Common Fields**\n * Fields required by the transport protocol.\n */\nexport const zBaseTransaction = z.object({\n /**\n * **Type**\n * REQUIRED. String that identifies the type of transaction data.\n * @source OpenID4VP Section 5.1\n */\n type: z.string(),\n /**\n * **Credential IDs**\n * REQUIRED. Non-empty array of strings each referencing a Credential requested\n * by the Verifier (via DCQL `id` or PEX) that authorizes this transaction.\n * @source OpenID4VP Section 5.1 \"transaction_data\"\n */\n credential_ids: z.tuple([z.string()]).rest(z.string()),\n\n /**\n * **Transaction Data Hashes Algorithm**\n * OPTIONAL. Array of hash algorithms (e.g. `[\"sha-256\"]`).\n * @source OpenID4VP Appendix B.3.3.1\n */\n transaction_data_hashes_alg: z.tuple([z.string()]).rest(z.string()).optional(),\n})\n","import { z } from 'zod'\nimport { zBaseTransaction } from './z-transaction-data-common'\n\n/**\n * **Funke (German) QES Authorization Data**\n * * Profile used by the SPRIND/Bundesdruckerei EUDI Wallet.\n * * This type bridges OpenID4VP with ETSI TS 119 432 (Remote Signing).\n * * @see German National EUDI Wallet Architecture (Appendix 07)\n */\nexport const zFunkeQesTransaction = zBaseTransaction.extend({\n /**\n * **Signature Qualifier**\n * The level of signature required.\n * @source ETSI TS 119 432\n */\n signatureQualifier: z\n .enum(['eu_eidas_qes', 'eu_eidas_aes'])\n .describe('eu_eidas_qes (Qualified) or eu_eidas_aes (Advanced)'),\n\n /**\n * **Document Digests**\n * List of document hashes to be signed (DTBS - Data To Be Signed).\n * @source ETSI TS 119 432\n */\n documentDigests: z\n .array(\n z.object({\n /**\n * **Label**\n * Human-readable filename displayed to the user.\n */\n label: z.string().describe(\"Filename (e.g. 'Contract.pdf')\"),\n\n /**\n * **Hash**\n * Base64 encoded hash of the document.\n */\n hash: z.string().describe('Base64 encoded hash'),\n\n /**\n * **Hash Algorithm OID**\n * Object Identifier for the hash algorithm.\n */\n hashAlgorithmOID: z.string().optional().describe('OID of the hash algorithm'),\n })\n )\n .min(1),\n})\nexport type FunkeQesTransactionDataEntry = z.infer<typeof zFunkeQesTransaction>\n","import { z } from 'zod'\nimport { zBaseTransaction } from './z-transaction-data-common'\n\n// =============================================================================\n// 1. TS12 PAYLOAD SCHEMAS (Nested Objects)\n// Source: EUDI TS12 Section 4.3 \"Payload Object\"\n// =============================================================================\n\n/**\n * **TS12 Payment Payload**\n * * The business data strictly defined for Payments.\n * * @see EUDI TS12 Section 4.3.1 \"Payment Confirmation\"\n */\nexport const zPaymentPayload = z\n .object({\n /**\n * **Transaction ID**\n * Unique identifier of the Relying Party's interaction with the User.\n * @example \"8D8AC610-566D-4EF0-9C22-186B2A5ED793\"\n */\n transaction_id: z.string().min(1).max(36).describe(\"Unique identifier of the Relying Party's interaction\"),\n\n /**\n * **Date Time**\n * ISO 8601 date and time when the Relying Party started to interact with the User.\n * @example \"2025-11-13T20:20:39+00:00\"\n */\n date_time: z.iso.datetime().optional(),\n\n /**\n * **Payee**\n * Object holding the Payee (Merchant) details.\n */\n payee: z.object({\n /**\n * **Payee Name**\n * Name of the Payee to whom the payment is being made.\n */\n name: z.string(),\n\n /**\n * **Payee ID**\n * An identifier of the Payee understood by the payment system.\n */\n id: z.string(),\n\n /**\n * **Logo**\n * Resolvable URL or Data URI (RFC 2397) of the Payee logo.\n */\n logo: z.url().optional(),\n\n /**\n * **Website**\n * Resolvable URL of the Payee's website.\n */\n website: z.url().optional(),\n }),\n\n /**\n * **Currency**\n * 3-letter currency code (ISO 4217).\n */\n currency: z.string().regex(/^[A-Z]{3}$/),\n\n /**\n * **Amount**\n * The monetary value of the transaction.\n */\n amount: z.number(),\n\n /**\n * **Amount Estimated**\n */\n amount_estimated: z.boolean().optional(),\n\n /**\n * **Amount Earmarked**\n */\n amount_earmarked: z.boolean().optional(),\n\n /**\n * **SCT Inst**\n */\n sct_inst: z.boolean().optional(),\n\n /**\n * **PISP Details**\n * If present, indicates that the payment is being facilitated by a PISP.\n */\n pisp: z\n .object({\n /**\n * **Legal Name**\n * Legal name of the PISP.\n */\n legal_name: z.string(),\n\n /**\n * **Brand Name**\n * Brand name of the PISP.\n */\n brand_name: z.string(),\n\n /**\n * **Domain Name**\n * Domain name of the PISP as secured by the eIDAS QWAC certificate.\n */\n domain_name: z.string(),\n })\n .optional(),\n\n /**\n * **Execution Date**\n * ISO 8601 date of the payment's execution. MUST NOT be present when recurrence is present.\n * MUST NOT lie in the past.\n */\n execution_date: z.iso\n .datetime()\n .optional()\n .refine(\n (date) => {\n if (!date) return true\n return new Date(date) >= new Date()\n },\n { message: 'Execution date must not be in the past' }\n ),\n\n /**\n * **Recurrence**\n * Details for recurring payments.\n */\n recurrence: z\n .object({\n /**\n * **Start Date**\n * ISO 8601 date when the recurrence starts.\n */\n start_date: z.iso.datetime().optional(),\n\n /**\n * **End Date**\n * ISO 8601 date when the recurrence ends.\n */\n end_date: z.iso.datetime().optional(),\n\n /**\n * **Number**\n */\n number: z.number().int().optional(),\n\n /**\n * **Frequency**\n * ISO 20022 Frequency Code.\n */\n frequency: z.enum([\n 'INDA',\n 'DAIL',\n 'WEEK',\n 'TOWK',\n 'TWMN',\n 'MNTH',\n 'TOMN',\n 'QUTR',\n 'FOMN',\n 'SEMI',\n 'YEAR',\n 'TYEA',\n ]),\n\n /**\n * **MIT Options (Merchant Initiated Transaction)**\n */\n mit_options: z\n .object({\n /**\n * **Amount Variable**\n * If true, future amounts may vary.\n */\n amount_variable: z.boolean().optional(),\n\n /**\n * **Minimum Amount**\n * Minimum expected amount for future transactions.\n */\n min_amount: z.number().optional(),\n\n /**\n * **Maximum Amount**\n */\n max_amount: z.number().optional(),\n\n /**\n * **Total Amount**\n */\n total_amount: z.number().optional(),\n\n /**\n * **Initial Amount**\n */\n initial_amount: z.number().optional(),\n\n /**\n * **Initial Amount Number**\n */\n initial_amount_number: z.number().int().optional(),\n\n /**\n * **APR**\n */\n apr: z.number().optional(),\n })\n .optional(),\n })\n .optional(),\n })\n .refine((data) => !(data.recurrence && data.execution_date), {\n message: 'Execution date must not be present when recurrence is present',\n path: ['execution_date'],\n })\n\n/**\n * **TS12 Login / Risk Payload**\n * * @see EUDI TS12 Section 4.3.2\n */\nexport const zLoginPayload = z.object({\n /**\n * **Transaction ID**\n * Unique identifier of the Relying Party's interaction.\n * @example \"8D8AC610-566D-4EF0-9C22-186B2A5ED793\"\n */\n transaction_id: z.string().min(1).max(36),\n\n /**\n * **Date Time**\n * @example \"2025-11-13T20:20:39+00:00\"\n */\n date_time: z.iso.datetime().optional(),\n\n /**\n * **Service**\n * Name of the service triggering the operation (e.g. \"Superbank Online\").\n * @example \"Superbank Onlinebanking\"\n */\n service: z.string().max(100).optional(),\n\n /**\n * **Action**\n * Description of the action (e.g. \"Log in\", \"Change limit\").\n * @example \"Login to your online account.\"\n */\n action: z.string().max(140).describe('Description of the action to be authorized'),\n})\n\n/**\n * **TS12 Account Access Payload**\n * * @see EUDI TS12 Section 4.3.3\n */\nexport const zAccountAccessPayload = z.object({\n /**\n * **Transaction ID**\n * @example \"8D8AC610-566D-4EF0-9C22-186B2A5ED793\"\n */\n transaction_id: z.string().min(1).max(36),\n\n /**\n * **Date Time**\n * @example \"2025-11-13T20:20:39+00:00\"\n */\n date_time: z.iso.datetime().optional(),\n\n /**\n * **AISP Details**\n * If present, indicates access facilitated by an AISP.\n */\n aisp: z\n .object({\n legal_name: z.string(),\n brand_name: z.string(),\n domain_name: z.string(),\n })\n .optional(),\n\n /**\n * **Description**\n * Description of the data access the user is agreeing to.\n * @example \"Grant access to the account's data.\"\n */\n description: z.string().max(140).optional(),\n})\n\n/**\n * **TS12 E-Mandate Payload**\n * * @see EUDI TS12 Section 4.3.4\n */\nexport const zEMandatePayload = z\n .object({\n /**\n * **Transaction ID**\n * @example \"8D8AC610-566D-4EF0-9C22-186B2A5ED793\"\n */\n transaction_id: z.string().min(1).max(36),\n\n /**\n * **Date Time**\n * @example \"2025-11-13T20:20:39+00:00\"\n */\n date_time: z.iso.datetime().optional(),\n\n /**\n * **Start Date**\n * When the mandate becomes valid.\n * @example \"2025-11-13T20:20:39+00:00\"\n */\n start_date: z.iso.datetime().optional(),\n\n /**\n * **End Date**\n * When the mandate expires.\n * @example \"2025-12-13T20:20:39+00:00\"\n */\n end_date: z.iso.datetime().optional(),\n\n /**\n * **Reference Number**\n * E.g. Mandate Reference Number.\n * @example \"A-98765\"\n */\n reference_number: z.string().min(1).max(50).optional(),\n\n /**\n * **Creditor ID**\n * SEPA Creditor Identifier.\n * @example \"FR14ZZZ001122334455\"\n */\n creditor_id: z.string().min(1).max(50).optional(),\n\n /**\n * **Purpose**\n * Mandate text. Required if payment_payload is missing.\n * @example \"Pay monthly bill\"\n */\n purpose: z.string().max(1000).optional(),\n\n /**\n * **Payment Payload**\n * Nested payment object to leverage data for MITs.\n */\n payment_payload: zPaymentPayload.optional(),\n })\n .refine((data) => data.payment_payload || data.purpose, {\n message: 'Purpose is required if payment_payload is missing',\n path: ['purpose'],\n })\n\nexport type Ts12AccountAccessPayload = z.infer<typeof zAccountAccessPayload>\nexport type Ts12EMandatePayload = z.infer<typeof zEMandatePayload>\nexport type Ts12LoginPayload = z.infer<typeof zLoginPayload>\nexport type Ts12PaymentPayload = z.infer<typeof zPaymentPayload>\n\nexport const URN_SCA_PAYMENT = 'urn:eudi:sca:payment:1'\nexport const URN_SCA_LOGIN_RISK = 'urn:eudi:sca:login_risk_transaction:1'\nexport const URN_SCA_ACCOUNT_ACCESS = 'urn:eudi:sca:account_access:1'\nexport const URN_SCA_EMANDATE = 'urn:eudi:sca:emandate:1'\n\n// =============================================================================\n// 2. ROOT TRANSACTION DATA OBJECT (OpenID4VP Envelope)\n// Source: OpenID4VP Section 5.1 & TS12 Section 4.3\n// =============================================================================\n\n/**\n * **TS12 Transaction**\n * @see TS12 Section 4.3\n */\nexport const zTs12Transaction = zBaseTransaction.extend({\n payload: z.union([zPaymentPayload, zLoginPayload, zAccountAccessPayload, zEMandatePayload, z.unknown()]),\n})\nexport type Ts12TransactionDataEntry = z.infer<typeof zTs12Transaction>\n","import { z } from 'zod'\nimport { zFunkeQesTransaction } from './z-transaction-data-funke'\nimport {\n URN_SCA_ACCOUNT_ACCESS,\n URN_SCA_EMANDATE,\n URN_SCA_LOGIN_RISK,\n URN_SCA_PAYMENT,\n zAccountAccessPayload,\n zEMandatePayload,\n zLoginPayload,\n zPaymentPayload,\n zTs12Transaction,\n} from './z-transaction-data-ts12'\n\nexport * from './z-transaction-data-funke'\nexport * from './z-transaction-data-ts12'\n\nexport const zTransactionDataEntry = zTs12Transaction.or(zFunkeQesTransaction)\nexport const zTransactionData = z.array(zTransactionDataEntry)\n\nexport type TransactionDataEntry = z.infer<typeof zTransactionDataEntry>\nexport type TransactionData = z.infer<typeof zTransactionDataEntry>\n\nexport const ts12BuiltinSchemaValidators = {\n [URN_SCA_PAYMENT]: zPaymentPayload,\n [URN_SCA_LOGIN_RISK]: zLoginPayload,\n [URN_SCA_ACCOUNT_ACCESS]: zAccountAccessPayload,\n [URN_SCA_EMANDATE]: zEMandatePayload,\n} as const\n","import { z } from 'zod'\nimport { Ts12IntegrityError } from '../error'\nimport {\n type ZScaAttestationExt,\n zScaTransactionDataTypeClaims,\n zScaTransactionDataTypeUiLabels,\n} from './z-sca-attestation-ext'\nimport { ts12BuiltinSchemaValidators } from './z-transaction-data'\n\nexport interface ResolvedTs12Metadata {\n schema: string | object\n claims: Array<{\n path: string[]\n visualisation: 1 | 2 | 3 | 4\n display: Array<{ name: string; locale?: string; logo?: string }>\n }>\n ui_labels: {\n affirmative_action_label: Array<{ lang: string; value: string }>\n denial_action_label?: Array<{ lang: string; value: string }>\n transaction_title?: Array<{ lang: string; value: string }>\n security_hint?: Array<{ lang: string; value: string }>\n }\n}\n\nasync function fetchVerified<T>(\n uri: string,\n schema: z.ZodType<T>,\n integrity?: string,\n validateIntegrity?: (buf: ArrayBuffer, integrity: string) => boolean\n): Promise<T> {\n const response = await fetch(uri)\n if (!response.ok) {\n throw new Error(`Failed to fetch URI: ${uri}`)\n }\n if (integrity && validateIntegrity && !validateIntegrity(await response.clone().arrayBuffer(), integrity)) {\n throw new Ts12IntegrityError(uri, integrity)\n }\n return schema.parse(await response.json())\n}\n\nexport async function resolveTs12TransactionDisplayMetadata(\n metadata: ZScaAttestationExt,\n type: string,\n validateIntegrity?: (buf: ArrayBuffer, integrity: string) => boolean\n): Promise<ResolvedTs12Metadata | undefined> {\n if (!metadata.transaction_data_types || !metadata.transaction_data_types[type]) {\n return undefined\n }\n\n const typeMetadata = metadata.transaction_data_types[type]\n const resolved: Partial<ResolvedTs12Metadata> = {}\n\n if ('schema' in typeMetadata && typeMetadata.schema) {\n if (!(typeMetadata.schema in ts12BuiltinSchemaValidators)) {\n throw new Error(`unknown builtin schema: ${typeMetadata.schema}`)\n }\n resolved.schema = typeMetadata.schema\n } else if ('schema_uri' in typeMetadata && typeMetadata.schema_uri) {\n resolved.schema = await fetchVerified(\n typeMetadata.schema_uri,\n z.object({}),\n typeMetadata['schema_uri#integrity'],\n validateIntegrity\n )\n } else {\n throw new Error(`Unknown schema type for ${typeMetadata}`)\n }\n\n if ('claims' in typeMetadata && typeMetadata.claims) {\n resolved.claims = typeMetadata.claims\n } else if ('claims_uri' in typeMetadata && typeMetadata.claims_uri) {\n resolved.claims = await fetchVerified(\n typeMetadata.claims_uri,\n zScaTransactionDataTypeClaims,\n typeMetadata['claims_uri#integrity'],\n validateIntegrity\n )\n } else {\n throw new Error(`Unknown claims for ${typeMetadata}`)\n }\n\n if ('ui_labels' in typeMetadata && typeMetadata.ui_labels) {\n resolved.ui_labels = typeMetadata.ui_labels\n } else if ('ui_labels_uri' in typeMetadata && typeMetadata.ui_labels_uri) {\n resolved.ui_labels = await fetchVerified(\n typeMetadata.ui_labels_uri,\n zScaTransactionDataTypeUiLabels,\n typeMetadata['ui_labels_uri#integrity'],\n validateIntegrity\n )\n } else {\n throw new Error(`Unknown ui_labels for ${typeMetadata}`)\n }\n\n return resolved as ResolvedTs12Metadata\n}\n","import { type DcqlQuery, equalsIgnoreOrder, equalsWithOrder } from '@credo-ts/core'\n\nexport function isDcqlQueryEqualOrSubset(arq: DcqlQuery, rcq: DcqlQuery): boolean {\n if (rcq.credential_sets) {\n return false\n }\n\n if (rcq.credentials.some((c) => c.id)) {\n return false\n }\n\n // only sd-jwt and mdoc are supported\n if (arq.credentials.some((c) => c.format !== 'mso_mdoc' && c.format !== 'vc+sd-jwt' && c.format !== 'dc+sd-jwt')) {\n return false\n }\n\n credentialQueryLoop: for (const credentialQuery of arq.credentials) {\n const matchingRcqCredentialQueriesBasedOnFormat = rcq.credentials.filter((c) => c.format === credentialQuery.format)\n\n if (matchingRcqCredentialQueriesBasedOnFormat.length === 0) return false\n\n switch (credentialQuery.format) {\n case 'mso_mdoc': {\n const doctypeValue = credentialQuery.meta?.doctype_value\n if (!doctypeValue) return false\n if (typeof credentialQuery.meta?.doctype_value !== 'string') return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & { format: 'mso_mdoc' } =>\n !!(c.format === 'mso_mdoc' && c.meta && c.meta.doctype_value === doctypeValue)\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for mdoc, this means matching the `path[0]` (namespace) and `path[1]` (value name)\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c &&\n matchedRequest.claims?.some(\n (mrc) => 'path' in mrc && c.path[0] === mrc.path[0] && c.path[1] === mrc.path[1]\n )\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n case 'dc+sd-jwt': {\n const vctValues = credentialQuery.meta?.vct_values\n if (!vctValues || vctValues.length === 0) return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & { format: 'dc+sd-jwt' } =>\n !!(c.format === 'dc+sd-jwt' && c.meta?.vct_values && equalsIgnoreOrder(c.meta.vct_values, vctValues))\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for sd-jwt, this means making sure that every `path[n]` is in the registration certificate\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c && matchedRequest.claims?.some((mrc) => 'path' in mrc && equalsWithOrder(c.path, mrc.path))\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n default:\n return false\n }\n }\n\n return true\n}\n","import { type AgentContext, type DcqlQuery, JwsService, Jwt, X509Certificate } from '@credo-ts/core'\nimport type { OpenId4VpResolvedAuthorizationRequest } from '@credo-ts/openid4vc'\nimport z from 'zod'\nimport { isDcqlQueryEqualOrSubset } from './isDcqlQueryEqualOrSubset'\n\nexport type VerifyAuthorizationRequestOptions = {\n resolvedAuthorizationRequest: OpenId4VpResolvedAuthorizationRequest\n trustedCertificates?: Array<string>\n allowUntrustedSigned?: boolean\n}\n\nexport const verifyOpenid4VpAuthorizationRequest = async (\n agentContext: AgentContext,\n {\n resolvedAuthorizationRequest: { authorizationRequestPayload, signedAuthorizationRequest, dcql },\n trustedCertificates,\n allowUntrustedSigned,\n }: VerifyAuthorizationRequestOptions\n) => {\n const results = []\n if (!authorizationRequestPayload.verifier_attestations) return\n for (const va of authorizationRequestPayload.verifier_attestations) {\n // Here we verify it as a registration certificate according to\n // https://bmi.usercontent.opencode.de/eudi-wallet/eidas-2.0-architekturkonzept/flows/Wallet-Relying-Party-Authentication/#registration-certificate\n if (va.format === 'jwt') {\n if (typeof va.data !== 'string') {\n throw new Error('Only inline JWTs are supported')\n }\n\n const jwsService = agentContext.dependencyManager.resolve(JwsService)\n\n let isValidButUntrusted = false\n let isValidAndTrusted = false\n\n const jwt = Jwt.fromSerializedJwt(va.data)\n\n try {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates,\n })\n isValidAndTrusted = isValid\n } catch {\n if (allowUntrustedSigned) {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates: jwt.header.x5c ?? [],\n })\n isValidButUntrusted = isValid\n }\n }\n\n if (jwt.header.typ !== 'rc-rp+jwt') {\n throw new Error(`only 'rc-rp+jwt' is supported as header typ. Request included: ${jwt.header.typ}`)\n }\n\n if (!signedAuthorizationRequest) {\n throw new Error('Request must be signed for the registration certificate')\n }\n\n if (signedAuthorizationRequest.signer.method !== 'x5c') {\n throw new Error('x5c is only supported for registration certificate')\n }\n\n const registrationCertificateHeaderSchema = z\n .object({\n typ: z.literal('rc-rp+jwt'),\n alg: z.string(),\n // sprin-d did not define this\n x5u: z.string().url().optional(),\n // sprin-d did not define this\n 'x5t#s256': z.string().optional(),\n })\n .passthrough()\n\n // TODO: does not support intermediaries\n const registrationCertificatePayloadSchema = z\n .object({\n credentials: z.array(\n z.object({\n format: z.string(),\n multiple: z.boolean().default(false),\n meta: z\n .object({\n vct_values: z.array(z.string()).optional(),\n doctype_value: z.string().optional(),\n })\n .optional(),\n trusted_authorities: z\n .array(z.object({ type: z.string(), values: z.array(z.string()) }))\n .nonempty()\n .optional(),\n require_cryptographic_holder_binding: z.boolean().default(true),\n claims: z\n .array(\n z.object({\n id: z.string().optional(),\n path: z.array(z.string()).nonempty().nonempty(),\n values: z.array(z.number().or(z.boolean())).optional(),\n })\n )\n .nonempty()\n .optional(),\n claim_sets: z.array(z.array(z.string())).nonempty().optional(),\n })\n ),\n contact: z.object({\n website: z.string().url(),\n 'e-mail': z.string().email(),\n phone: z.string(),\n }),\n sub: z.string(),\n // Should be service\n services: z.array(z.object({ lang: z.string(), name: z.string() })),\n public_body: z.boolean().default(false),\n entitlements: z.array(z.any()),\n provided_attestations: z\n .array(\n z.object({\n format: z.string(),\n meta: z.any(),\n })\n )\n .optional(),\n privacy_policy: z.string().url(),\n iat: z.number().optional(),\n exp: z.number().optional(),\n purpose: z\n .array(\n z.object({\n locale: z.string().optional(),\n lang: z.string().optional(),\n name: z.string(),\n })\n )\n .optional(),\n status: z.any(),\n })\n .passthrough()\n\n registrationCertificateHeaderSchema.parse(jwt.header)\n const parsedPayload = registrationCertificatePayloadSchema.parse(jwt.payload.toJson())\n\n const [rpCertEncoded] = signedAuthorizationRequest.signer.x5c\n const rpCert = X509Certificate.fromEncodedCertificate(rpCertEncoded)\n\n if (rpCert.subject !== parsedPayload.sub) {\n throw new Error(\n `Subject in the certificate of the auth request: '${rpCert.subject}' is not equal to the subject of the registration certificate: '${parsedPayload.sub}'`\n )\n }\n\n if (parsedPayload.iat && Date.now() / 1000 <= parsedPayload.iat) {\n throw new Error('Issued at timestamp of the registration certificate is in the future')\n }\n\n // TODO: check the status of the registration certificate\n\n if (!dcql) {\n throw new Error('DCQL must be used when working registration certificates')\n }\n\n if (\n authorizationRequestPayload.presentation_definition ||\n authorizationRequestPayload.presentation_definition_uri\n ) {\n throw new Error('Presentation Exchange is not supported for the registration certificate')\n }\n\n const isValidDcqlQuery = isDcqlQueryEqualOrSubset(dcql.queryResult, parsedPayload as unknown as DcqlQuery)\n\n if (!isValidDcqlQuery) {\n throw new Error(\n 'DCQL query in the authorization request is not equal or a valid subset of the DCQl query provided in the registration certificate'\n )\n }\n\n results.push({ isValidButUntrusted, isValidAndTrusted, x509RegistrationCertificate: rpCert })\n } else {\n throw new Error(`only format of 'jwt' is supported`)\n }\n }\n return results\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@animo-id/eudi-wallet-functionality",
|
|
3
3
|
"description": "EUDI Wallet Functionality",
|
|
4
|
-
"version": "0.0.0-alpha-
|
|
4
|
+
"version": "0.0.0-alpha-20260108162340",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Animo Solutions",
|
|
7
7
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
-
"import": "./dist/index.mjs",
|
|
10
|
-
"require": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts"
|
|
12
|
-
},
|
|
8
|
+
".": "./build/index.mjs",
|
|
13
9
|
"./package.json": "./package.json"
|
|
14
10
|
},
|
|
15
11
|
"files": [
|
|
@@ -27,31 +23,30 @@
|
|
|
27
23
|
"@credo-ts/openid4vc": "*"
|
|
28
24
|
},
|
|
29
25
|
"devDependencies": {
|
|
30
|
-
"@biomejs/biome": "^
|
|
31
|
-
"@changesets/cli": "^2.29.
|
|
32
|
-
"@credo-ts/askar": "0.6.
|
|
33
|
-
"@credo-ts/core": "0.6.
|
|
34
|
-
"@credo-ts/node": "0.6.
|
|
35
|
-
"@credo-ts/openid4vc": "0.6.
|
|
36
|
-
"@openwallet-foundation/askar-nodejs": "^0.3
|
|
26
|
+
"@biomejs/biome": "^2.3.11",
|
|
27
|
+
"@changesets/cli": "^2.29.8",
|
|
28
|
+
"@credo-ts/askar": "^0.6.1",
|
|
29
|
+
"@credo-ts/core": "^0.6.1",
|
|
30
|
+
"@credo-ts/node": "^0.6.1",
|
|
31
|
+
"@credo-ts/openid4vc": "^0.6.1",
|
|
32
|
+
"@openwallet-foundation/askar-nodejs": "^0.4.3",
|
|
37
33
|
"@types/node": "^22.15.29",
|
|
38
|
-
"
|
|
39
|
-
"tsx": "^4.
|
|
40
|
-
"typescript": "~5.
|
|
34
|
+
"tsdown": "^0.18.4",
|
|
35
|
+
"tsx": "^4.21.0",
|
|
36
|
+
"typescript": "~5.9.3"
|
|
41
37
|
},
|
|
42
38
|
"dependencies": {
|
|
43
|
-
"zod": "^3.
|
|
39
|
+
"zod": "^4.3.5"
|
|
44
40
|
},
|
|
45
41
|
"scripts": {
|
|
46
42
|
"types:check": "tsc --noEmit",
|
|
47
43
|
"style:check": "biome check --unsafe",
|
|
48
44
|
"style:fix": "biome check --write --unsafe",
|
|
49
|
-
"build": "
|
|
45
|
+
"build": "tsdown src/index.ts --format esm --dts --clean --sourcemap",
|
|
50
46
|
"test": "node --import tsx --test tests/*.test.ts",
|
|
51
47
|
"release": "pnpm build && pnpm changeset publish --no-git-tag",
|
|
52
48
|
"changeset-version": "pnpm changeset version && pnpm style:fix"
|
|
53
49
|
},
|
|
54
|
-
"main": "./dist/index.js",
|
|
55
50
|
"module": "./dist/index.mjs",
|
|
56
|
-
"types": "./dist/index.d.
|
|
51
|
+
"types": "./dist/index.d.mts"
|
|
57
52
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { AgentContext, X509Certificate } from '@credo-ts/core';
|
|
2
|
-
import { OpenId4VpResolvedAuthorizationRequest } from '@credo-ts/openid4vc';
|
|
3
|
-
|
|
4
|
-
type VerifyAuthorizationRequestOptions = {
|
|
5
|
-
resolvedAuthorizationRequest: OpenId4VpResolvedAuthorizationRequest;
|
|
6
|
-
trustedCertificates?: Array<string>;
|
|
7
|
-
allowUntrustedSigned?: boolean;
|
|
8
|
-
};
|
|
9
|
-
declare const verifyOpenid4VpAuthorizationRequest: (agentContext: AgentContext, { resolvedAuthorizationRequest: { authorizationRequestPayload, signedAuthorizationRequest, dcql }, trustedCertificates, allowUntrustedSigned, }: VerifyAuthorizationRequestOptions) => Promise<{
|
|
10
|
-
isValidButUntrusted: boolean;
|
|
11
|
-
isValidAndTrusted: boolean;
|
|
12
|
-
x509RegistrationCertificate: X509Certificate;
|
|
13
|
-
}[] | undefined>;
|
|
14
|
-
|
|
15
|
-
export { verifyOpenid4VpAuthorizationRequest };
|
package/dist/index.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
verifyOpenid4VpAuthorizationRequest: () => verifyOpenid4VpAuthorizationRequest
|
|
34
|
-
});
|
|
35
|
-
module.exports = __toCommonJS(index_exports);
|
|
36
|
-
|
|
37
|
-
// src/verifyOpenid4VpAuthorizationRequest.ts
|
|
38
|
-
var import_core2 = require("@credo-ts/core");
|
|
39
|
-
var import_zod = __toESM(require("zod"));
|
|
40
|
-
|
|
41
|
-
// src/isDcqlQueryEqualOrSubset.ts
|
|
42
|
-
var import_core = require("@credo-ts/core");
|
|
43
|
-
function isDcqlQueryEqualOrSubset(arq, rcq) {
|
|
44
|
-
if (rcq.credential_sets) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
if (rcq.credentials.some((c) => c.id)) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
if (arq.credentials.some((c) => c.format !== "mso_mdoc" && c.format !== "vc+sd-jwt" && c.format !== "dc+sd-jwt")) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
credentialQueryLoop: for (const credentialQuery of arq.credentials) {
|
|
54
|
-
const matchingRcqCredentialQueriesBasedOnFormat = rcq.credentials.filter((c) => c.format === credentialQuery.format);
|
|
55
|
-
if (matchingRcqCredentialQueriesBasedOnFormat.length === 0) return false;
|
|
56
|
-
switch (credentialQuery.format) {
|
|
57
|
-
case "mso_mdoc": {
|
|
58
|
-
const doctypeValue = credentialQuery.meta?.doctype_value;
|
|
59
|
-
if (!doctypeValue) return false;
|
|
60
|
-
if (typeof credentialQuery.meta?.doctype_value !== "string") return false;
|
|
61
|
-
const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(
|
|
62
|
-
(c) => !!(c.format === "mso_mdoc" && c.meta && c.meta.doctype_value === doctypeValue)
|
|
63
|
-
);
|
|
64
|
-
if (foundMatchingRequests.length === 0) return false;
|
|
65
|
-
let foundFullyMatching = false;
|
|
66
|
-
for (const matchedRequest of foundMatchingRequests) {
|
|
67
|
-
if (!matchedRequest.claims) continue credentialQueryLoop;
|
|
68
|
-
if (!credentialQuery.claims) continue credentialQueryLoop;
|
|
69
|
-
const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(
|
|
70
|
-
(c) => "path" in c && matchedRequest.claims?.some(
|
|
71
|
-
(mrc) => "path" in mrc && c.path[0] === mrc.path[0] && c.path[1] === mrc.path[1]
|
|
72
|
-
)
|
|
73
|
-
);
|
|
74
|
-
if (isEveryClaimAllowedToBeRequested) {
|
|
75
|
-
foundFullyMatching = true;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (!foundFullyMatching) return false;
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
case "dc+sd-jwt":
|
|
82
|
-
case "vc+sd-jwt": {
|
|
83
|
-
const vctValues = credentialQuery.meta?.vct_values;
|
|
84
|
-
if (!vctValues) return false;
|
|
85
|
-
if (credentialQuery.meta?.vct_values?.length === 0) return false;
|
|
86
|
-
const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(
|
|
87
|
-
(c) => !!((c.format === "dc+sd-jwt" || c.format === "vc+sd-jwt") && c.meta?.vct_values && (0, import_core.equalsIgnoreOrder)(c.meta.vct_values, vctValues))
|
|
88
|
-
);
|
|
89
|
-
if (foundMatchingRequests.length === 0) return false;
|
|
90
|
-
let foundFullyMatching = false;
|
|
91
|
-
for (const matchedRequest of foundMatchingRequests) {
|
|
92
|
-
if (!matchedRequest.claims) continue credentialQueryLoop;
|
|
93
|
-
if (!credentialQuery.claims) continue credentialQueryLoop;
|
|
94
|
-
const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(
|
|
95
|
-
(c) => "path" in c && matchedRequest.claims?.some((mrc) => "path" in mrc && (0, import_core.equalsWithOrder)(c.path, mrc.path))
|
|
96
|
-
);
|
|
97
|
-
if (isEveryClaimAllowedToBeRequested) {
|
|
98
|
-
foundFullyMatching = true;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (!foundFullyMatching) return false;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
default:
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// src/verifyOpenid4VpAuthorizationRequest.ts
|
|
112
|
-
var verifyOpenid4VpAuthorizationRequest = async (agentContext, {
|
|
113
|
-
resolvedAuthorizationRequest: { authorizationRequestPayload, signedAuthorizationRequest, dcql },
|
|
114
|
-
trustedCertificates,
|
|
115
|
-
allowUntrustedSigned
|
|
116
|
-
}) => {
|
|
117
|
-
const results = [];
|
|
118
|
-
if (!authorizationRequestPayload.verifier_attestations) return;
|
|
119
|
-
for (const va of authorizationRequestPayload.verifier_attestations) {
|
|
120
|
-
if (va.format === "jwt") {
|
|
121
|
-
if (typeof va.data !== "string") {
|
|
122
|
-
throw new Error("Only inline JWTs are supported");
|
|
123
|
-
}
|
|
124
|
-
const jwsService = agentContext.dependencyManager.resolve(import_core2.JwsService);
|
|
125
|
-
let isValidButUntrusted = false;
|
|
126
|
-
let isValidAndTrusted = false;
|
|
127
|
-
const jwt = import_core2.Jwt.fromSerializedJwt(va.data);
|
|
128
|
-
try {
|
|
129
|
-
const { isValid } = await jwsService.verifyJws(agentContext, {
|
|
130
|
-
jws: va.data,
|
|
131
|
-
trustedCertificates
|
|
132
|
-
});
|
|
133
|
-
isValidAndTrusted = isValid;
|
|
134
|
-
} catch {
|
|
135
|
-
if (allowUntrustedSigned) {
|
|
136
|
-
const { isValid } = await jwsService.verifyJws(agentContext, {
|
|
137
|
-
jws: va.data,
|
|
138
|
-
trustedCertificates: jwt.header.x5c ?? []
|
|
139
|
-
});
|
|
140
|
-
isValidButUntrusted = isValid;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (jwt.header.typ !== "rc-rp+jwt") {
|
|
144
|
-
throw new Error(`only 'rc-rp+jwt' is supported as header typ. Request included: ${jwt.header.typ}`);
|
|
145
|
-
}
|
|
146
|
-
if (!signedAuthorizationRequest) {
|
|
147
|
-
throw new Error("Request must be signed for the registration certificate");
|
|
148
|
-
}
|
|
149
|
-
if (signedAuthorizationRequest.signer.method !== "x5c") {
|
|
150
|
-
throw new Error("x5c is only supported for registration certificate");
|
|
151
|
-
}
|
|
152
|
-
const registrationCertificateHeaderSchema = import_zod.default.object({
|
|
153
|
-
typ: import_zod.default.literal("rc-rp+jwt"),
|
|
154
|
-
alg: import_zod.default.string(),
|
|
155
|
-
// sprin-d did not define this
|
|
156
|
-
x5u: import_zod.default.string().url().optional(),
|
|
157
|
-
// sprin-d did not define this
|
|
158
|
-
"x5t#s256": import_zod.default.string().optional()
|
|
159
|
-
}).passthrough();
|
|
160
|
-
const registrationCertificatePayloadSchema = import_zod.default.object({
|
|
161
|
-
credentials: import_zod.default.array(
|
|
162
|
-
import_zod.default.object({
|
|
163
|
-
format: import_zod.default.string(),
|
|
164
|
-
multiple: import_zod.default.boolean().default(false),
|
|
165
|
-
meta: import_zod.default.object({
|
|
166
|
-
vct_values: import_zod.default.array(import_zod.default.string()).optional(),
|
|
167
|
-
doctype_value: import_zod.default.string().optional()
|
|
168
|
-
}).optional(),
|
|
169
|
-
trusted_authorities: import_zod.default.array(import_zod.default.object({ type: import_zod.default.string(), values: import_zod.default.array(import_zod.default.string()) })).nonempty().optional(),
|
|
170
|
-
require_cryptographic_holder_binding: import_zod.default.boolean().default(true),
|
|
171
|
-
claims: import_zod.default.array(
|
|
172
|
-
import_zod.default.object({
|
|
173
|
-
id: import_zod.default.string().optional(),
|
|
174
|
-
path: import_zod.default.array(import_zod.default.string()).nonempty().nonempty(),
|
|
175
|
-
values: import_zod.default.array(import_zod.default.number().or(import_zod.default.boolean())).optional()
|
|
176
|
-
})
|
|
177
|
-
).nonempty().optional(),
|
|
178
|
-
claim_sets: import_zod.default.array(import_zod.default.array(import_zod.default.string())).nonempty().optional()
|
|
179
|
-
})
|
|
180
|
-
),
|
|
181
|
-
contact: import_zod.default.object({
|
|
182
|
-
website: import_zod.default.string().url(),
|
|
183
|
-
"e-mail": import_zod.default.string().email(),
|
|
184
|
-
phone: import_zod.default.string()
|
|
185
|
-
}),
|
|
186
|
-
sub: import_zod.default.string(),
|
|
187
|
-
// Should be service
|
|
188
|
-
services: import_zod.default.array(import_zod.default.object({ lang: import_zod.default.string(), name: import_zod.default.string() })),
|
|
189
|
-
public_body: import_zod.default.boolean().default(false),
|
|
190
|
-
entitlements: import_zod.default.array(import_zod.default.any()),
|
|
191
|
-
provided_attestations: import_zod.default.array(
|
|
192
|
-
import_zod.default.object({
|
|
193
|
-
format: import_zod.default.string(),
|
|
194
|
-
meta: import_zod.default.any()
|
|
195
|
-
})
|
|
196
|
-
).optional(),
|
|
197
|
-
privacy_policy: import_zod.default.string().url(),
|
|
198
|
-
iat: import_zod.default.number().optional(),
|
|
199
|
-
exp: import_zod.default.number().optional(),
|
|
200
|
-
purpose: import_zod.default.array(
|
|
201
|
-
import_zod.default.object({
|
|
202
|
-
locale: import_zod.default.string().optional(),
|
|
203
|
-
lang: import_zod.default.string().optional(),
|
|
204
|
-
name: import_zod.default.string()
|
|
205
|
-
})
|
|
206
|
-
).optional(),
|
|
207
|
-
status: import_zod.default.any()
|
|
208
|
-
}).passthrough();
|
|
209
|
-
registrationCertificateHeaderSchema.parse(jwt.header);
|
|
210
|
-
const parsedPayload = registrationCertificatePayloadSchema.parse(jwt.payload.toJson());
|
|
211
|
-
const [rpCertEncoded] = signedAuthorizationRequest.signer.x5c;
|
|
212
|
-
const rpCert = import_core2.X509Certificate.fromEncodedCertificate(rpCertEncoded);
|
|
213
|
-
if (rpCert.subject !== parsedPayload.sub) {
|
|
214
|
-
throw new Error(
|
|
215
|
-
`Subject in the certificate of the auth request: '${rpCert.subject}' is not equal to the subject of the registration certificate: '${parsedPayload.sub}'`
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
if (parsedPayload.iat && (/* @__PURE__ */ new Date()).getTime() / 1e3 <= parsedPayload.iat) {
|
|
219
|
-
throw new Error("Issued at timestamp of the registration certificate is in the future");
|
|
220
|
-
}
|
|
221
|
-
if (!dcql) {
|
|
222
|
-
throw new Error("DCQL must be used when working registration certificates");
|
|
223
|
-
}
|
|
224
|
-
if (authorizationRequestPayload.presentation_definition || authorizationRequestPayload.presentation_definition_uri) {
|
|
225
|
-
throw new Error("Presentation Exchange is not supported for the registration certificate");
|
|
226
|
-
}
|
|
227
|
-
const isValidDcqlQuery = isDcqlQueryEqualOrSubset(dcql.queryResult, parsedPayload);
|
|
228
|
-
if (!isValidDcqlQuery) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
"DCQL query in the authorization request is not equal or a valid subset of the DCQl query provided in the registration certificate"
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
results.push({ isValidButUntrusted, isValidAndTrusted, x509RegistrationCertificate: rpCert });
|
|
234
|
-
} else {
|
|
235
|
-
throw new Error(`only format of 'jwt' is supported`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return results;
|
|
239
|
-
};
|
|
240
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
241
|
-
0 && (module.exports = {
|
|
242
|
-
verifyOpenid4VpAuthorizationRequest
|
|
243
|
-
});
|
|
244
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/verifyOpenid4VpAuthorizationRequest.ts","../src/isDcqlQueryEqualOrSubset.ts"],"sourcesContent":["export { verifyOpenid4VpAuthorizationRequest } from './verifyOpenid4VpAuthorizationRequest'\n","import { type AgentContext, type DcqlQuery, JwsService, Jwt, X509Certificate } from '@credo-ts/core'\nimport type { OpenId4VpResolvedAuthorizationRequest } from '@credo-ts/openid4vc'\nimport z from 'zod'\nimport { isDcqlQueryEqualOrSubset } from './isDcqlQueryEqualOrSubset'\n\nexport type VerifyAuthorizationRequestOptions = {\n resolvedAuthorizationRequest: OpenId4VpResolvedAuthorizationRequest\n trustedCertificates?: Array<string>\n allowUntrustedSigned?: boolean\n}\n\nexport const verifyOpenid4VpAuthorizationRequest = async (\n agentContext: AgentContext,\n {\n resolvedAuthorizationRequest: { authorizationRequestPayload, signedAuthorizationRequest, dcql },\n trustedCertificates,\n allowUntrustedSigned,\n }: VerifyAuthorizationRequestOptions\n) => {\n const results = []\n if (!authorizationRequestPayload.verifier_attestations) return\n for (const va of authorizationRequestPayload.verifier_attestations) {\n // Here we verify it as a registration certificate according to\n // https://bmi.usercontent.opencode.de/eudi-wallet/eidas-2.0-architekturkonzept/flows/Wallet-Relying-Party-Authentication/#registration-certificate\n if (va.format === 'jwt') {\n if (typeof va.data !== 'string') {\n throw new Error('Only inline JWTs are supported')\n }\n\n const jwsService = agentContext.dependencyManager.resolve(JwsService)\n\n let isValidButUntrusted = false\n let isValidAndTrusted = false\n\n const jwt = Jwt.fromSerializedJwt(va.data)\n\n try {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates,\n })\n isValidAndTrusted = isValid\n } catch {\n if (allowUntrustedSigned) {\n const { isValid } = await jwsService.verifyJws(agentContext, {\n jws: va.data,\n trustedCertificates: jwt.header.x5c ?? [],\n })\n isValidButUntrusted = isValid\n }\n }\n\n if (jwt.header.typ !== 'rc-rp+jwt') {\n throw new Error(`only 'rc-rp+jwt' is supported as header typ. Request included: ${jwt.header.typ}`)\n }\n\n if (!signedAuthorizationRequest) {\n throw new Error('Request must be signed for the registration certificate')\n }\n\n if (signedAuthorizationRequest.signer.method !== 'x5c') {\n throw new Error('x5c is only supported for registration certificate')\n }\n\n const registrationCertificateHeaderSchema = z\n .object({\n typ: z.literal('rc-rp+jwt'),\n alg: z.string(),\n // sprin-d did not define this\n x5u: z.string().url().optional(),\n // sprin-d did not define this\n 'x5t#s256': z.string().optional(),\n })\n .passthrough()\n\n // TODO: does not support intermediaries\n const registrationCertificatePayloadSchema = z\n .object({\n credentials: z.array(\n z.object({\n format: z.string(),\n multiple: z.boolean().default(false),\n meta: z\n .object({\n vct_values: z.array(z.string()).optional(),\n doctype_value: z.string().optional(),\n })\n .optional(),\n trusted_authorities: z\n .array(z.object({ type: z.string(), values: z.array(z.string()) }))\n .nonempty()\n .optional(),\n require_cryptographic_holder_binding: z.boolean().default(true),\n claims: z\n .array(\n z.object({\n id: z.string().optional(),\n path: z.array(z.string()).nonempty().nonempty(),\n values: z.array(z.number().or(z.boolean())).optional(),\n })\n )\n .nonempty()\n .optional(),\n claim_sets: z.array(z.array(z.string())).nonempty().optional(),\n })\n ),\n contact: z.object({\n website: z.string().url(),\n 'e-mail': z.string().email(),\n phone: z.string(),\n }),\n sub: z.string(),\n // Should be service\n services: z.array(z.object({ lang: z.string(), name: z.string() })),\n public_body: z.boolean().default(false),\n entitlements: z.array(z.any()),\n provided_attestations: z\n .array(\n z.object({\n format: z.string(),\n meta: z.any(),\n })\n )\n .optional(),\n privacy_policy: z.string().url(),\n iat: z.number().optional(),\n exp: z.number().optional(),\n purpose: z\n .array(\n z.object({\n locale: z.string().optional(),\n lang: z.string().optional(),\n name: z.string(),\n })\n )\n .optional(),\n status: z.any(),\n })\n .passthrough()\n\n registrationCertificateHeaderSchema.parse(jwt.header)\n const parsedPayload = registrationCertificatePayloadSchema.parse(jwt.payload.toJson())\n\n const [rpCertEncoded] = signedAuthorizationRequest.signer.x5c\n const rpCert = X509Certificate.fromEncodedCertificate(rpCertEncoded)\n\n if (rpCert.subject !== parsedPayload.sub) {\n throw new Error(\n `Subject in the certificate of the auth request: '${rpCert.subject}' is not equal to the subject of the registration certificate: '${parsedPayload.sub}'`\n )\n }\n\n if (parsedPayload.iat && new Date().getTime() / 1000 <= parsedPayload.iat) {\n throw new Error('Issued at timestamp of the registration certificate is in the future')\n }\n\n // TODO: check the status of the registration certificate\n\n if (!dcql) {\n throw new Error('DCQL must be used when working registration certificates')\n }\n\n if (\n authorizationRequestPayload.presentation_definition ||\n authorizationRequestPayload.presentation_definition_uri\n ) {\n throw new Error('Presentation Exchange is not supported for the registration certificate')\n }\n\n const isValidDcqlQuery = isDcqlQueryEqualOrSubset(dcql.queryResult, parsedPayload as unknown as DcqlQuery)\n\n if (!isValidDcqlQuery) {\n throw new Error(\n 'DCQL query in the authorization request is not equal or a valid subset of the DCQl query provided in the registration certificate'\n )\n }\n\n results.push({ isValidButUntrusted, isValidAndTrusted, x509RegistrationCertificate: rpCert })\n } else {\n throw new Error(`only format of 'jwt' is supported`)\n }\n }\n return results\n}\n","import { type DcqlQuery, equalsIgnoreOrder, equalsWithOrder } from '@credo-ts/core'\n\nexport function isDcqlQueryEqualOrSubset(arq: DcqlQuery, rcq: DcqlQuery): boolean {\n if (rcq.credential_sets) {\n return false\n }\n\n if (rcq.credentials.some((c) => c.id)) {\n return false\n }\n\n // only sd-jwt and mdoc are supported\n if (arq.credentials.some((c) => c.format !== 'mso_mdoc' && c.format !== 'vc+sd-jwt' && c.format !== 'dc+sd-jwt')) {\n return false\n }\n\n credentialQueryLoop: for (const credentialQuery of arq.credentials) {\n const matchingRcqCredentialQueriesBasedOnFormat = rcq.credentials.filter((c) => c.format === credentialQuery.format)\n\n if (matchingRcqCredentialQueriesBasedOnFormat.length === 0) return false\n\n switch (credentialQuery.format) {\n case 'mso_mdoc': {\n const doctypeValue = credentialQuery.meta?.doctype_value\n if (!doctypeValue) return false\n if (typeof credentialQuery.meta?.doctype_value !== 'string') return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & { format: 'mso_mdoc' } =>\n !!(c.format === 'mso_mdoc' && c.meta && c.meta.doctype_value === doctypeValue)\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for mdoc, this means matching the `path[0]` (namespace) and `path[1]` (value name)\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c &&\n matchedRequest.claims?.some(\n (mrc) => 'path' in mrc && c.path[0] === mrc.path[0] && c.path[1] === mrc.path[1]\n )\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n case 'dc+sd-jwt':\n case 'vc+sd-jwt': {\n const vctValues = credentialQuery.meta?.vct_values\n if (!vctValues) return false\n if (credentialQuery.meta?.vct_values?.length === 0) return false\n\n const foundMatchingRequests = matchingRcqCredentialQueriesBasedOnFormat.filter(\n (c): c is typeof c & ({ format: 'dc+sd-jwt' } | { format: 'vc+sd-jwt' }) =>\n !!(\n (c.format === 'dc+sd-jwt' || c.format === 'vc+sd-jwt') &&\n c.meta?.vct_values &&\n equalsIgnoreOrder(c.meta.vct_values, vctValues)\n )\n )\n\n // We do not know which one we have to pick based on the meta+format\n if (foundMatchingRequests.length === 0) return false\n\n let foundFullyMatching = false\n for (const matchedRequest of foundMatchingRequests) {\n // credentialQuery.claims must match or be subset of matchedRequest\n\n // If the claims is empty, everything within the specific format+meta is allowed\n if (!matchedRequest.claims) continue credentialQueryLoop\n\n // If no specific claims are request, we allow it as the format+meta is allowed to be requested\n // but this requests no additional claims\n if (!credentialQuery.claims) continue credentialQueryLoop\n\n // Every claim request in the authorization request must be found in the registration certificate\n // for sd-jwt, this means making sure that every `path[n]` is in the registration certificate\n const isEveryClaimAllowedToBeRequested = credentialQuery.claims.every(\n (c) =>\n 'path' in c && matchedRequest.claims?.some((mrc) => 'path' in mrc && equalsWithOrder(c.path, mrc.path))\n )\n if (isEveryClaimAllowedToBeRequested) {\n foundFullyMatching = true\n }\n }\n\n if (!foundFullyMatching) return false\n\n break\n }\n default:\n return false\n }\n }\n\n return true\n}\n"],"mappings":"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","names":["import_core","z"]}
|