From 2cc45e707b866afb23e33231b1380add246365e1 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 18 Nov 2024 18:38:45 +0100 Subject: [PATCH 01/60] chore: Added federation_entity metadata to siop/oid4vp and oid4vci --- .../oid4vci-common/lib/types/v1_0_13.types.ts | 16 ++++++++++- packages/siop-oid4vp/lib/types/SIOP.types.ts | 27 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/oid4vci-common/lib/types/v1_0_13.types.ts b/packages/oid4vci-common/lib/types/v1_0_13.types.ts index e601f4d9..3bb4720d 100644 --- a/packages/oid4vci-common/lib/types/v1_0_13.types.ts +++ b/packages/oid4vci-common/lib/types/v1_0_13.types.ts @@ -189,6 +189,18 @@ export interface CredentialOfferPayloadV1_0_13 { client_id?: string; } +export interface FederationEntityMetadataOpts { + federation_fetch_endpoint?: string + federation_list_endpoint?: string + federation_resolve_endpoint?: string + federation_trust_mark_status_endpoint?: string + federation_trust_mark_list_endpoint?: string + federation_trust_mark_endpoint?: string + federation_historical_keys_endpoint?: string + organization_name?: string + homepage_uri?: string +} + export interface CredentialIssuerMetadataOptsV1_0_13 { credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. batch_credential_endpoint?: string; // OPTIONAL. URL of the Credential Issuer's Batch Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. If omitted, the Credential Issuer does not support the Batch Credential Endpoint. @@ -205,6 +217,7 @@ export interface CredentialIssuerMetadataOptsV1_0_13 { //todo: these two are not mentioned in the spec token_endpoint?: string; credential_supplier_config?: CredentialSupplierConfig; + federation_entity?: FederationEntityMetadataOpts } // These can be used be a reducer @@ -226,7 +239,8 @@ export const credentialIssuerMetadataFieldNames: Array Date: Wed, 20 Nov 2024 13:13:36 +0100 Subject: [PATCH 02/60] feat: dcql alpha --- package.json | 4 +- .../AuthorizationRequest.ts | 30 ++++-- .../lib/authorization-request/Payload.ts | 18 +++- .../lib/authorization-request/URI.ts | 8 +- .../lib/authorization-request/types.ts | 4 +- .../AuthorizationResponse.ts | 33 ++++--- .../lib/authorization-response/Dcql.ts | 44 +++++++++ .../lib/authorization-response/OpenID4VP.ts | 99 ++++++++++++------- .../PresentationExchange.ts | 4 +- .../lib/authorization-response/types.ts | 16 ++- .../lib/helpers/SIOPSpecVersion.ts | 3 +- packages/siop-oid4vp/lib/op/OP.ts | 34 ++++--- .../siop-oid4vp/lib/request-object/Payload.ts | 1 + packages/siop-oid4vp/lib/rp/RP.ts | 4 + packages/siop-oid4vp/lib/rp/RPBuilder.ts | 18 ++++ packages/siop-oid4vp/lib/types/Errors.ts | 2 +- packages/siop-oid4vp/lib/types/SIOP.types.ts | 7 ++ packages/siop-oid4vp/package.json | 1 + pnpm-lock.yaml | 3 + 19 files changed, 245 insertions(+), 88 deletions(-) create mode 100644 packages/siop-oid4vp/lib/authorization-response/Dcql.ts diff --git a/package.json b/package.json index 35f5b75b..ac994988 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,6 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ] + ], + "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" } - diff --git a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts index 13316a70..aeb4b15b 100644 --- a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts +++ b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts @@ -1,6 +1,8 @@ import { parseJWT } from '@sphereon/oid4vc-common' +import { DcqlQuery } from 'dcql' import { PresentationDefinitionWithLocation } from '../authorization-response' +import { findValidDcqlQuery } from '../authorization-response/Dcql' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { fetchByReferenceOrUseByValue, removeNullUndefined } from '../helpers' import { authorizationRequestVersionDiscovery } from '../helpers/SIOPSpecVersion' @@ -66,7 +68,7 @@ export class AuthorizationRequest { const requestObjectArg = opts.requestObject.passBy !== PassBy.NONE ? (requestObject ? requestObject : await RequestObject.fromOpts(opts)) : undefined - // opts?.payload was removed before, but it's not clear atm why opts?.payload was removed + // opts?.payload was removed before, but it's not clear atm why opts?.payload was removed const requestPayload = opts?.payload ? await createAuthorizationRequestPayload(opts, requestObjectArg) : undefined return new AuthorizationRequest(requestPayload, requestObjectArg, opts) } @@ -190,14 +192,22 @@ export class AuthorizationRequest { // TODO see if this is too naive. The OpenID conformance test explicitly tests for this // But the spec says: The client_id and client_id_scheme MUST be omitted in unsigned requests defined in Appendix A.3.1. // So I would expect client_id_scheme and client_id to be undefined when the JWT header has alg: none - if(mergedPayload.client_id && mergedPayload.client_id_scheme === 'redirect_uri' && mergedPayload.client_id !== responseURI) { - throw Error(`${SIOPErrors.INVALID_REQUEST}, response_uri does not match the client_id provided by the verifier which is required for client_id_scheme redirect_uri`) + if (mergedPayload.client_id && mergedPayload.client_id_scheme === 'redirect_uri' && mergedPayload.client_id !== responseURI) { + throw Error( + `${SIOPErrors.INVALID_REQUEST}, response_uri does not match the client_id provided by the verifier which is required for client_id_scheme redirect_uri`, + ) } - + // TODO: we need to verify somewhere that if response_mode is direct_post, that the response_uri may be present, // BUT not both redirect_uri and response_uri. What is the best place to do this? - const presentationDefinitions: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions(mergedPayload, await this.getSupportedVersion()) + const presentationDefinitions: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions( + mergedPayload, + await this.getSupportedVersion(), + ) + + const dcqlQuery = await findValidDcqlQuery(mergedPayload) + return { jwt, payload: parsedJwt?.payload, @@ -208,6 +218,7 @@ export class AuthorizationRequest { correlationId: opts.correlationId, authorizationRequest: this, verifyOpts: opts, + dcqlQuery, presentationDefinitions, registrationMetadataPayload, requestObject: this.requestObject, @@ -267,8 +278,9 @@ export class AuthorizationRequest { } public async mergedPayloads(): Promise { - const requestObjectPayload = { ...this.payload, ...(this.requestObject && (await this.requestObject.getPayload())) } - if (requestObjectPayload.scope && typeof requestObjectPayload.scope !== 'string') { // test mattr.launchpad.spec.ts does not supply a scope value + const requestObjectPayload = { ...this.payload, ...(this.requestObject && (await this.requestObject.getPayload())) } + if (requestObjectPayload.scope && typeof requestObjectPayload.scope !== 'string') { + // test mattr.launchpad.spec.ts does not supply a scope value throw new Error('Invalid scope value') } return requestObjectPayload as RequestObjectPayload @@ -277,4 +289,8 @@ export class AuthorizationRequest { public async getPresentationDefinitions(version?: SupportedVersion): Promise { return await PresentationExchange.findValidPresentationDefinitions(await this.mergedPayloads(), version) } + + public async getDcqlQuery(): Promise { + return await findValidDcqlQuery(await this.mergedPayloads()) + } } diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index 3219f700..b21d7c70 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -18,20 +18,28 @@ import { createRequestRegistration } from './RequestRegistration' import { ClaimPayloadOptsVID1, CreateAuthorizationRequestOpts, PropertyTarget } from './types' export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadOptsVID1): ClaimPayloadVID1 => { - if (!opts || !opts.vp_token || (!opts.vp_token.presentation_definition && !opts.vp_token.presentation_definition_uri)) { + if ( + !opts || + !opts.vp_token || + (!opts.vp_token.presentation_definition && !opts.vp_token.presentation_definition_uri && !opts.vp_token.dcql_query) + ) { return undefined } - const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) - if (discoveryResult.error) { - throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) + + if (opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri) { + const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) + if (discoveryResult.error) { + throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) + } } return { ...(opts.id_token ? { id_token: opts.id_token } : {}), - ...((opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri) && { + ...((opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri || opts.vp_token.dcql_query) && { vp_token: { ...(!opts.vp_token.presentation_definition_uri && { presentation_definition: opts.vp_token.presentation_definition }), ...(opts.vp_token.presentation_definition_uri && { presentation_definition_uri: opts.vp_token.presentation_definition_uri }), + ...(opts.vp_token.dcql_query && { dcql_query: opts.vp_token.dcql_query }), }, }), } diff --git a/packages/siop-oid4vp/lib/authorization-request/URI.ts b/packages/siop-oid4vp/lib/authorization-request/URI.ts index 7aa04815..f6bf42bc 100644 --- a/packages/siop-oid4vp/lib/authorization-request/URI.ts +++ b/packages/siop-oid4vp/lib/authorization-request/URI.ts @@ -1,5 +1,6 @@ import { parseJWT } from '@sphereon/oid4vc-common' +import { findValidDcqlQuery } from '../authorization-response/Dcql' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { decodeUriAsJson, encodeJsonAsURI, fetchByReferenceOrUseByValue } from '../helpers' import { assertValidRequestObjectPayload, RequestObject } from '../request-object' @@ -126,7 +127,6 @@ export class URI implements AuthorizationRequestURI { ...authorizationRequest.options.requestObject, version: authorizationRequest.options.version, uriScheme: authorizationRequest.options.uriScheme, - }, authorizationRequest.payload, authorizationRequest.requestObject, @@ -164,8 +164,9 @@ export class URI implements AuthorizationRequestURI { const requestObjectPayload: RequestObjectPayload = requestObjectJwt ? (parseJWT(requestObjectJwt).payload as RequestObjectPayload) : undefined if (requestObjectPayload) { - // Only used to validate if the request object contains presentation definition(s) + // Only used to validate if the request object contains presentation definition(s) | a dcql query await PresentationExchange.findValidPresentationDefinitions({ ...authorizationRequestPayload, ...requestObjectPayload }) + await findValidDcqlQuery({ ...authorizationRequestPayload, ...requestObjectPayload }) assertValidRequestObjectPayload(requestObjectPayload) if (requestObjectPayload.registration) { @@ -194,7 +195,8 @@ export class URI implements AuthorizationRequestURI { } } else { try { - scheme = (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' + scheme = + (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' } catch (error: unknown) { scheme = 'openid4vp://' } diff --git a/packages/siop-oid4vp/lib/authorization-request/types.ts b/packages/siop-oid4vp/lib/authorization-request/types.ts index 64956db9..da1abd0c 100644 --- a/packages/siop-oid4vp/lib/authorization-request/types.ts +++ b/packages/siop-oid4vp/lib/authorization-request/types.ts @@ -1,7 +1,7 @@ import { SigningAlgo } from '@sphereon/oid4vc-common' import { Hasher } from '@sphereon/ssi-types' -import { PresentationDefinitionPayloadOpts } from '../authorization-response' +import { DcqlQueryPayloadOpts, PresentationDefinitionPayloadOpts } from '../authorization-response' import { RequestObjectOpts } from '../request-object' import { ClientIdScheme, @@ -19,7 +19,7 @@ import { VerifyJwtCallback } from '../types/VpJwtVerifier' export interface ClaimPayloadOptsVID1 extends ClaimPayloadCommonOpts { id_token?: IdTokenClaimPayload - vp_token?: PresentationDefinitionPayloadOpts + vp_token?: PresentationDefinitionPayloadOpts | DcqlQueryPayloadOpts } export interface ClaimPayloadCommonOpts { diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 64c3cc54..de5f1b3a 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -124,21 +124,25 @@ export class AuthorizationResponse { }) if (hasVpToken) { - const wrappedPresentations = response.payload.vp_token - ? await extractPresentationsFromVpToken(response.payload.vp_token, { + if (responseOpts.presentationExchange) { + const wrappedPresentations = response.payload.vp_token + ? await extractPresentationsFromVpToken(response.payload.vp_token, { + hasher: verifyOpts.hasher, + }) + : [] + + await assertValidVerifiablePresentations({ + presentationDefinitions, + presentations: wrappedPresentations, + verificationCallback: verifyOpts.verification.presentationVerificationCallback, + opts: { + ...responseOpts.presentationExchange, hasher: verifyOpts.hasher, - }) - : [] - - await assertValidVerifiablePresentations({ - presentationDefinitions, - presentations: wrappedPresentations, - verificationCallback: verifyOpts.verification.presentationVerificationCallback, - opts: { - ...responseOpts.presentationExchange, - hasher: verifyOpts.hasher, - }, - }) + }, + }) + } else { + throw new Error('TODO: VALIDATE PRESENTATION AGAINST DEFINITION') + } } return response @@ -219,7 +223,6 @@ export class AuthorizationResponse { } const presentationsArray = Array.isArray(presentations) ? presentations : [presentations] - // We do not verify them, as that is done elsewhere. So we simply can take the first nonce nonce = presentationsArray // FIXME toWrappedVerifiablePresentation() does not extract the nonce yet from mdocs. diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts new file mode 100644 index 00000000..e67fb783 --- /dev/null +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -0,0 +1,44 @@ +import { DcqlQuery } from 'dcql' + +import { extractDataFromPath } from '../helpers' +import { AuthorizationRequestPayload, SIOPErrors } from '../types' + +/** + * Finds a valid DcqlQuery inside the given AuthenticationRequestPayload + * throws exception if the DcqlQuery is not valid + * returns the decoded dcql query if a valid instance found + * @param authorizationRequestPayload object that can have a dcql_query inside + * @param version + */ +export const findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise => { + const vpTokens: string[] = extractDataFromPath(authorizationRequestPayload, '$..vp_token.dcql_query').map((d) => d.value) + const vpTokensList: string[] = extractDataFromPath(authorizationRequestPayload, '$..vp_token.dcql_query[*]').map((d) => d.value) + const definitions = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition') + const definitionsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition[*]') + const definitionRefs = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri') + const definitionRefsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri[*]') + + const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) + const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) + const hasDcql = (vpTokens && vpTokens.length > 0) || (vpTokensList && vpTokensList.length > 0) + + if ([hasPD, hasPdRef, hasDcql].filter(Boolean).length > 1) { + throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) + } + + if (!(vpTokens && vpTokens.length) && !(vpTokensList && vpTokensList.length)) { + throw new Error('Cannot find dcql_query in vp_token. Presentation definition is present') + } + + if (vpTokens.length > 1 && vpTokensList.length > 1) { + throw new Error('Found multiple dcql_query in vp_token. Only one is allowed') + } + + const encoded = vpTokens.length ? vpTokens[0] : vpTokensList[0] + if (!encoded) return undefined + + const dcqlQuery = DcqlQuery.parse(JSON.parse(encoded)) + DcqlQuery.validate(dcqlQuery) + + return dcqlQuery +} diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 0db13b81..ec76bd4d 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -10,6 +10,7 @@ import { W3CVerifiablePresentation, WrappedVerifiablePresentation, } from '@sphereon/ssi-types' +import { DcqlQuery, DcqlQueryVpToken } from 'dcql' import { AuthorizationRequest } from '../authorization-request' import { verifyRevocation } from '../helpers' @@ -70,46 +71,76 @@ export const verifyPresentations = async ( authorizationResponse: AuthorizationResponse, verifyOpts: VerifyAuthorizationResponseOpts, ): Promise => { - if (!authorizationResponse.payload.vp_token || Array.isArray(authorizationResponse.payload.vp_token) && authorizationResponse.payload.vp_token.length === 0) { + if ( + !authorizationResponse.payload.vp_token || + (Array.isArray(authorizationResponse.payload.vp_token) && authorizationResponse.payload.vp_token.length === 0) + ) { return Promise.reject(Error('the payload is missing a vp_token')) } - - const presentations = await extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) - const presentationDefinitions = verifyOpts.presentationDefinitions - ? Array.isArray(verifyOpts.presentationDefinitions) - ? verifyOpts.presentationDefinitions - : [verifyOpts.presentationDefinitions] - : [] + let idPayload: IDTokenPayload | undefined if (authorizationResponse.idToken) { idPayload = await authorizationResponse.idToken.payload() } + // todo: Probably wise to check against request for the location of the submission_data const presentationSubmission = idPayload?._vp_token?.presentation_submission ?? authorizationResponse.payload.presentation_submission - await assertValidVerifiablePresentations({ - presentationDefinitions, - presentations, - verificationCallback: verifyOpts.verification.presentationVerificationCallback, - opts: { - presentationSubmission, - restrictToFormats: verifyOpts.restrictToFormats, - restrictToDIDMethods: verifyOpts.restrictToDIDMethods, - hasher: verifyOpts.hasher, - }, - }) + let wrappedPresentations: WrappedVerifiablePresentation[] = [] + const presentationDefinitions = verifyOpts.presentationDefinitions + ? Array.isArray(verifyOpts.presentationDefinitions) + ? verifyOpts.presentationDefinitions + : [verifyOpts.presentationDefinitions] + : [] + + const dcqlQuery = verifyOpts.dcqlQuery ?? authorizationResponse.authorizationRequest.payload.dcql_query + if (dcqlQuery) { + const dcqlQueryVpToken = DcqlQueryVpToken.parse(JSON.parse(authorizationResponse.payload.vp_token as string)) + + const parsedQuery = DcqlQuery.parse(dcqlQuery) + DcqlQuery.validate(parsedQuery) + + const presentations = Object.values(dcqlQueryVpToken) as Array + wrappedPresentations = presentations.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: verifyOpts.hasher })) + + const verifiedPresentations = await Promise.all( + presentations.map((presentation) => verifyOpts.verification.presentationVerificationCallback(presentation, presentationSubmission)), + ) + + // TODO: assert the submission against the definition + + if (verifiedPresentations.some((verified) => !verified)) { + const message = verifiedPresentations + .map((verified) => verified.reason) + .filter(Boolean) + .join(', ') + + throw Error(`Failed to verify presentations. ${message}`) + } + } else { + const presentations = await extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) + wrappedPresentations = Array.isArray(presentations) ? presentations : [presentations] + + await assertValidVerifiablePresentations({ + presentationDefinitions, + presentations, + verificationCallback: verifyOpts.verification.presentationVerificationCallback, + opts: { + presentationSubmission, + restrictToFormats: verifyOpts.restrictToFormats, + restrictToDIDMethods: verifyOpts.restrictToDIDMethods, + hasher: verifyOpts.hasher, + }, + }) + } // If there are no presentations, and the `assertValidVerifiablePresentations` did not fail // it means there's no oid4vp response and also not requested - if (Array.isArray(presentations) && presentations.length === 0) { + if (wrappedPresentations.length === 0) { return null } - if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) { - return Promise.reject(Error('missing presentation(s)')) - } - const presentationsArray = Array.isArray(presentations) ? presentations : [presentations] - const presentationsWithoutMdoc = presentationsArray.filter((p) => p.format !== 'mso_mdoc') + const presentationsWithoutMdoc = wrappedPresentations.filter((p) => p.format !== 'mso_mdoc') const nonces = new Set(presentationsWithoutMdoc.map(extractNonceFromWrappedVerifiablePresentation)) if (presentationsWithoutMdoc.length > 0 && nonces.size !== 1) { throw Error(`${nonces.size} nonce values found for ${presentationsWithoutMdoc.length}. Should be 1`) @@ -128,24 +159,22 @@ export const verifyPresentations = async ( if (!verifyOpts.verification.revocationOpts?.revocationVerificationCallback) { throw Error(`Please provide a revocation callback as revocation checking of credentials and presentations is not disabled`) } - for (const vp of presentationsArray) { + for (const vp of wrappedPresentations) { await verifyRevocation(vp, verifyOpts.verification.revocationOpts.revocationVerificationCallback, revocationVerification) } } - return { nonce, presentations: presentationsArray, presentationDefinitions, submissionData: presentationSubmission } + return { nonce, presentations: wrappedPresentations, presentationDefinitions, submissionData: presentationSubmission } } export const extractPresentationsFromVpToken = async ( vpToken: Array | W3CVerifiablePresentation | CompactSdJwtVc | string, opts?: { hasher?: Hasher }, ): Promise => { - const tokens = Array.isArray(vpToken) ? vpToken : [vpToken]; - const wrappedTokens = tokens.map(vp => - CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: opts?.hasher }) - ); + const tokens = Array.isArray(vpToken) ? vpToken : [vpToken] + const wrappedTokens = tokens.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: opts?.hasher })) - return tokens.length === 1 ? wrappedTokens[0] : wrappedTokens; - } + return tokens.length === 1 ? wrappedTokens[0] : wrappedTokens +} export const createPresentationSubmission = async ( verifiablePresentations: W3CVerifiablePresentation[], @@ -285,8 +314,8 @@ export const assertValidVerifiablePresentations = async (args: { presentationSubmission?: PresentationSubmission hasher?: Hasher } -}) : Promise => { - const {presentations} = args +}): Promise => { + const { presentations } = args if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) { return Promise.reject(Error('missing presentation(s)')) } diff --git a/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts b/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts index 18764cb1..cae54fb5 100644 --- a/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts +++ b/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts @@ -195,7 +195,7 @@ export class PresentationExchange { ).map((d) => d.value) const vpTokenRefs = extractDataFromPath(authorizationRequestPayload, '$..vp_token.presentation_definition_uri') if (vpTokens && vpTokens.length && vpTokenRefs && vpTokenRefs.length) { - throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_BY_REF_AND_VALUE_NON_EXCLUSIVE) + throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) } if (vpTokens && vpTokens.length) { vpTokens.forEach((vpToken: PresentationDefinitionV1 | PresentationDefinitionV2) => { @@ -252,7 +252,7 @@ export class PresentationExchange { const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) if (hasPD && hasPdRef) { - throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_BY_REF_AND_VALUE_NON_EXCLUSIVE) + throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) } if (definitions && definitions.length > 0) { definitions.forEach((definition) => { diff --git a/packages/siop-oid4vp/lib/authorization-response/types.ts b/packages/siop-oid4vp/lib/authorization-response/types.ts index 9ec19ddc..9a6e1bf2 100644 --- a/packages/siop-oid4vp/lib/authorization-response/types.ts +++ b/packages/siop-oid4vp/lib/authorization-response/types.ts @@ -5,10 +5,11 @@ import { CompactSdJwtVc, Hasher, MdocOid4vpIssuerSigned, + MdocOid4vpMdocVpToken, PresentationSubmission, W3CVerifiablePresentation, - MdocOid4vpMdocVpToken, } from '@sphereon/ssi-types' +import { DcqlQuery, DcqlQueryVpToken } from 'dcql' import { ResponseMode, @@ -41,6 +42,7 @@ export interface AuthorizationResponseOpts { tokenType?: string refreshToken?: string presentationExchange?: PresentationExchangeResponseOpts + dcqlQuery?: DcqlQueryResponseOpts } export interface PresentationExchangeResponseOpts { @@ -59,6 +61,10 @@ export interface PresentationExchangeResponseOpts { restrictToDIDMethods?: string[] } +export interface DcqlQueryResponseOpts { + credentialQueryIdToPresentation: DcqlQueryVpToken +} + export interface PresentationExchangeRequestOpts { presentationVerificationCallback?: PresentationVerificationCallback } @@ -66,6 +72,13 @@ export interface PresentationExchangeRequestOpts { export interface PresentationDefinitionPayloadOpts { presentation_definition?: IPresentationDefinition presentation_definition_uri?: string + dcql_query?: never +} + +export interface DcqlQueryPayloadOpts { + dcql_query?: string + presentation_definition?: never + presentation_definition_uri?: never } export interface PresentationDefinitionWithLocation { @@ -108,6 +121,7 @@ export interface VerifyAuthorizationResponseOpts { nonce?: string // To verify the response against the supplied nonce state?: string // To verify the response against the supplied state presentationDefinitions?: PresentationDefinitionWithLocation | PresentationDefinitionWithLocation[] // The presentation definitions to match against VPs in the response + dcqlQuery?: DcqlQuery audience?: string // The audience/redirect_uri restrictToFormats?: Format // Further restrict to certain VC formats, not expressed in the presentation definition restrictToDIDMethods?: string[] diff --git a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts index 2e0d9d77..5e41e4e8 100644 --- a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts +++ b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts @@ -29,7 +29,8 @@ function isID1Payload(authorizationRequest: AuthorizationRequestPayload) { !authorizationRequest.client_metadata_uri && !authorizationRequest.client_metadata && !authorizationRequest.presentation_definition && - !authorizationRequest.presentation_definition_uri + !authorizationRequest.presentation_definition_uri && + !authorizationRequest.dcql_query ) } diff --git a/packages/siop-oid4vp/lib/op/OP.ts b/packages/siop-oid4vp/lib/op/OP.ts index 7fee9a0a..e4fa29fb 100644 --- a/packages/siop-oid4vp/lib/op/OP.ts +++ b/packages/siop-oid4vp/lib/op/OP.ts @@ -1,15 +1,16 @@ -import { EventEmitter } from 'events'; +import { EventEmitter } from 'events' import { jarmAuthResponseSend, JarmClientMetadata, jarmMetadataValidate, JarmServerMetadata } from '@sphereon/jarm' -import { JwtIssuer, uuidv4 } from '@sphereon/oid4vc-common'; -import { IIssuerId } from '@sphereon/ssi-types'; +import { JwtIssuer, uuidv4 } from '@sphereon/oid4vc-common' +import { IIssuerId } from '@sphereon/ssi-types' -import { AuthorizationRequest, URI, VerifyAuthorizationRequestOpts } from '../authorization-request'; -import { mergeVerificationOpts } from '../authorization-request/Opts'; +import { AuthorizationRequest, URI, VerifyAuthorizationRequestOpts } from '../authorization-request' +import { mergeVerificationOpts } from '../authorization-request/Opts' import { AuthorizationResponse, AuthorizationResponseOpts, AuthorizationResponseWithCorrelationId, + DcqlQueryResponseOpts, PresentationExchangeResponseOpts, } from '../authorization-response' import { encodeJsonAsURI, post } from '../helpers' @@ -29,11 +30,11 @@ import { SupportedVersion, UrlEncodingFormat, Verification, - VerifiedAuthorizationRequest -} from '../types'; + VerifiedAuthorizationRequest, +} from '../types' -import { OPBuilder } from './OPBuilder'; -import { createResponseOptsFromBuilderOrExistingOpts, createVerifyRequestOptsFromBuilderOrExistingOpts } from './Opts'; +import { OPBuilder } from './OPBuilder' +import { createResponseOptsFromBuilderOrExistingOpts, createVerifyRequestOptsFromBuilderOrExistingOpts } from './Opts' // The OP publishes the formats it supports using the vp_formats_supported metadata parameter as defined above in its "openid-configuration". export class OP { @@ -78,7 +79,7 @@ export class OP { try { const verifiedAuthorizationRequest = await authorizationRequest.verify( - this.newVerifyAuthorizationRequestOpts({ ...requestOpts, correlationId }) + this.newVerifyAuthorizationRequestOpts({ ...requestOpts, correlationId }), ) await this.emitEvent(AuthorizationEvents.ON_AUTH_REQUEST_VERIFIED_SUCCESS, { @@ -106,6 +107,7 @@ export class OP { issuer?: ResponseIss | string verification?: Verification presentationExchange?: PresentationExchangeResponseOpts + dcqlQuery?: DcqlQueryResponseOpts }, ): Promise { if ( @@ -235,7 +237,7 @@ export class OP { const { response } = await createJarmResponse({ requestObjectPayload, authorizationResponsePayload: payload, - clientMetadata + clientMetadata, }) try { @@ -243,9 +245,9 @@ export class OP { authRequestParams: { response_uri: responseUri, response_mode: responseMode, - response_type: responseType + response_type: responseType, }, - authResponse: response + authResponse: response, }) void this.emitEvent(AuthorizationEvents.ON_AUTH_RESPONSE_SENT_SUCCESS, { correlationId, subject: response }) return jarmResponse @@ -253,7 +255,7 @@ export class OP { void this.emitEvent(AuthorizationEvents.ON_AUTH_RESPONSE_SENT_FAILED, { correlationId, subject: response, - error + error, }) throw error } @@ -294,6 +296,7 @@ export class OP { issuer?: IIssuerId | ResponseIss audience?: string presentationExchange?: PresentationExchangeResponseOpts + dcqlQuery?: DcqlQueryResponseOpts }): AuthorizationResponseOpts { const version = opts.version ?? this._createResponseOptions.version let issuer = opts.issuer ?? this._createResponseOptions?.registration?.issuer @@ -308,11 +311,14 @@ export class OP { } // We are taking the whole presentationExchange object from a certain location const presentationExchange = opts.presentationExchange ?? this._createResponseOptions.presentationExchange + const dcqlQuery = opts.dcqlQuery ?? this._createResponseOptions.dcqlQuery + const responseURI = opts.audience ?? this._createResponseOptions.responseURI return { ...this._createResponseOptions, ...opts, ...(presentationExchange && { presentationExchange }), + ...(dcqlQuery && { dcqlQuery }), registration: { ...this._createResponseOptions?.registration, issuer }, responseURI, responseURIType: diff --git a/packages/siop-oid4vp/lib/request-object/Payload.ts b/packages/siop-oid4vp/lib/request-object/Payload.ts index 59991031..661c7ee3 100644 --- a/packages/siop-oid4vp/lib/request-object/Payload.ts +++ b/packages/siop-oid4vp/lib/request-object/Payload.ts @@ -48,6 +48,7 @@ export const createRequestObjectPayload = async (opts: CreateAuthorizationReques claims, presentation_definition_uri: payload.presentation_definition_uri, presentation_definition: payload.presentation_definition, + dcql_query: payload.dcql_query, client_metadata: payload.client_metadata, iat, nbf, diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index d165dac2..addc9a23 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -8,6 +8,7 @@ import { } from '@sphereon/jarm' import { decodeProtectedHeader, JwtIssuer, uuidv4 } from '@sphereon/oid4vc-common' import { Hasher } from '@sphereon/ssi-types' +import { DcqlQuery } from 'dcql' import { AuthorizationRequest, @@ -202,6 +203,7 @@ export class RP { nonce?: string verification?: Verification presentationDefinitions?: PresentationDefinitionWithLocation | PresentationDefinitionWithLocation[] + dcqlQuery?: DcqlQuery }, ): Promise { const state = opts?.state || this.verifyResponseOptions.state @@ -376,6 +378,7 @@ export class RP { verification?: Verification audience?: string presentationDefinitions?: PresentationDefinitionWithLocation | PresentationDefinitionWithLocation[] + dcqlQuery?: DcqlQuery }, ): Promise { let correlationId = opts?.correlationId ?? this._verifyResponseOptions.correlationId @@ -418,6 +421,7 @@ export class RP { nonce, verification: mergeVerificationOpts(this._verifyResponseOptions, opts), presentationDefinitions: opts?.presentationDefinitions ?? this._verifyResponseOptions.presentationDefinitions, + dcqlQuery: opts?.dcqlQuery ?? this._verifyResponseOptions.dcqlQuery, } } diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index fbbdec63..c27b01b1 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -218,6 +218,24 @@ export class RPBuilder { return this } + withDcqlQuery(dcqlQuery: string, targets?: PropertyTargets): RPBuilder { + this._authorizationRequestPayload.dcql_query = assignIfAuth( + { + propertyValue: dcqlQuery, + targets, + }, + false, + ) + this._requestObjectPayload.dcql_query = assignIfRequestObject( + { + propertyValue: dcqlQuery, + targets, + }, + true, + ) + return this + } + withPresentationDefinition(definitionOpts: { definition: IPresentationDefinition; definitionUri?: string }, targets?: PropertyTargets): RPBuilder { const { definition, definitionUri } = definitionOpts diff --git a/packages/siop-oid4vp/lib/types/Errors.ts b/packages/siop-oid4vp/lib/types/Errors.ts index 24c36f92..780d8c17 100644 --- a/packages/siop-oid4vp/lib/types/Errors.ts +++ b/packages/siop-oid4vp/lib/types/Errors.ts @@ -38,7 +38,7 @@ enum SIOPErrors { REFERENCE_URI_NO_PAYLOAD = 'referenceUri specified, but object to host there is not present', NO_SELF_ISSUED_ISS = 'The Response Token Issuer Claim (iss) MUST start with https://self-isued.me/v2', REGISTRATION_NOT_SET = 'Registration metadata not set.', - REQUEST_CLAIMS_PRESENTATION_DEFINITION_BY_REF_AND_VALUE_NON_EXCLUSIVE = "Request claims can't have both 'presentation_definition' and 'presentation_definition_uri'", + REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE = "Request claims can't multiple of 'presentation_definition' and 'presentation_definition_uri' 'dcql_query", REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID = 'Presentation definition in the request claims is not valid', REQUEST_OBJECT_TYPE_NOT_SET = 'Request object type is not set.', RESPONSE_OPTS_PRESENTATIONS_SUBMISSION_IS_NOT_VALID = 'presentation_submission object inside the response opts vp should be valid', diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index a104d0b7..30619c0f 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -13,6 +13,7 @@ import { W3CVerifiablePresentation, WrappedVerifiablePresentation, } from '@sphereon/ssi-types' +import { DcqlQuery } from 'dcql' import { AuthorizationRequest, CreateAuthorizationRequestOpts, PropertyTargets, VerifyAuthorizationRequestOpts } from '../authorization-request' import { @@ -98,6 +99,7 @@ export interface AuthorizationRequestPayloadVD12OID4VPD20 presentation_definition_uri?: string client_id_scheme?: ClientIdSchemeOID4VPD20 response_uri?: string // New since OID4VP18 OPTIONAL. The Response URI to which the Wallet MUST send the Authorization Response using an HTTPS POST request as defined by the Response Mode direct_post. The Response URI receives all Authorization Response parameters as defined by the respective Response Type. When the response_uri parameter is present, the redirect_uri Authorization Request parameter MUST NOT be present. If the redirect_uri Authorization Request parameter is present when the Response Mode is direct_post, the Wallet MUST return an invalid_request Authorization Response error. + dcql_query?: string } export type ClientIdSchemeOID4VPD18 = 'pre-registered' | 'redirect_uri' | 'entity_id' | 'did' @@ -139,6 +141,7 @@ export interface VerifiedAuthorizationRequest extends Partial { requestObject?: RequestObject // The Request object registrationMetadataPayload: RPRegistrationMetadataPayload presentationDefinitions?: PresentationDefinitionWithLocation[] // The optional presentation definition objects that the RP requests + dcqlQuery?: DcqlQuery verifyOpts: VerifyAuthorizationRequestOpts // The verification options for the authentication request versions: SupportedVersion[] } @@ -164,6 +167,8 @@ export interface IDTokenPayload extends JWTPayload { } } +export type DcqlQueryVpToken = string + export interface AuthorizationResponsePayload { access_token?: string token_type?: string @@ -176,6 +181,7 @@ export interface AuthorizationResponsePayload { | W3CVerifiablePresentation | CompactSdJwtVc | MdocOid4vpMdocVpToken + | DcqlQueryVpToken presentation_submission?: PresentationSubmission verifiedData?: IPresentation | AdditionalClaims // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -190,6 +196,7 @@ export interface IdTokenClaimPayload { export interface VpTokenClaimPayload { presentation_definition?: PresentationDefinitionV1 | PresentationDefinitionV2 presentation_definition_uri?: string + dcql_query?: string } export interface ClaimPayloadCommon { diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index bc687cf5..ad8ea863 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,6 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", + "dcql": "link:../../../dcql/dcql", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.129", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7378a309..b16db23d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -460,6 +460,9 @@ importers: cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) + dcql: + specifier: link:../../../dcql/dcql + version: link:../../../dcql/dcql debug: specifier: ^4.3.5 version: 4.3.7 From e9fb7cc4065b948ef040022159a11f91c7f40671 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 20 Nov 2024 13:31:48 +0100 Subject: [PATCH 03/60] chore: Added openid_credential_verifier into the client registration metadata --- .../AuthorizationRequestPayloadVD11.schema.ts | 210 +++++++++ ...ationRequestPayloadVD12OID4VPD18.schema.ts | 210 +++++++++ ...ationRequestPayloadVD12OID4VPD20.schema.ts | 210 +++++++++ .../AuthorizationRequestPayloadVID1.schema.ts | 210 +++++++++ .../AuthorizationResponseOpts.schema.ts | 412 ++++++++++++++---- .../DiscoveryMetadataPayload.schema.ts | 409 +++++++++++++---- .../RPRegistrationMetadataPayload.schema.ts | 210 +++++++++ packages/siop-oid4vp/lib/types/SIOP.types.ts | 6 + 8 files changed, 1699 insertions(+), 178 deletions(-) diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts index 020c0299..f863fe85 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts @@ -209,6 +209,72 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { {} ] }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_name": { "anyOf": [ { @@ -400,6 +466,150 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { ], "additionalProperties": false }, + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false + }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts index bb6429d1..70b075d6 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts @@ -215,6 +215,72 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { {} ] }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_name": { "anyOf": [ { @@ -406,6 +472,150 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { ], "additionalProperties": false }, + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false + }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts index 42961fb7..efbd7209 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts @@ -215,6 +215,72 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { {} ] }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_name": { "anyOf": [ { @@ -406,6 +472,150 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { ], "additionalProperties": false }, + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false + }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts index 0b78c774..c0573572 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts @@ -181,6 +181,72 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { {} ] }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_name": { "anyOf": [ { @@ -372,6 +438,150 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { ], "additionalProperties": false }, + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false + }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index ffb4eee2..0cb365d1 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -431,6 +431,72 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, + "federationEntity": { + "$ref": "#/definitions/FederationEntityMetadataOpts" + }, + "openidCredentialVerifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "type": "string" }, @@ -500,6 +566,7 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ + "openidCredentialVerifier", "passBy" ] }, @@ -866,6 +933,72 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, + "federationEntity": { + "$ref": "#/definitions/FederationEntityMetadataOpts" + }, + "openidCredentialVerifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "type": "string" }, @@ -929,6 +1062,7 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ + "openidCredentialVerifier", "passBy" ] }, @@ -1295,6 +1429,72 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, + "federationEntity": { + "$ref": "#/definitions/FederationEntityMetadataOpts" + }, + "openidCredentialVerifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "idTokenTypesSupported": { "anyOf": [ { @@ -1313,6 +1513,7 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ + "openidCredentialVerifier", "passBy" ] } @@ -1449,116 +1650,38 @@ export const AuthorizationResponseOptsSchemaObj = { "distributed" ] }, - "JWKS": { + "FederationEntityMetadataOpts": { "type": "object", "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { + "federationFetchEndpoint": { "type": "string" }, - "crv": { + "federationListEndpoint": { "type": "string" }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { + "federationResolveEndpoint": { "type": "string" }, - "n": { + "federationTrustMarkStatusEndpoint": { "type": "string" }, - "alg": { + "federationTrustMarkListEndpoint": { "type": "string" }, - "d": { + "federationTrustMarkEndpoint": { "type": "string" }, - "dp": { + "federationHistoricalKeysEndpoint": { "type": "string" }, - "dq": { + "organizationName": { "type": "string" }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { + "homepageUri": { "type": "string" } }, - "additionalProperties": {} + "additionalProperties": false }, "Format": { "type": "object", @@ -1690,6 +1813,117 @@ export const AuthorizationResponseOptsSchemaObj = { ], "additionalProperties": false }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "IdTokenType": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts b/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts index ba4f744b..0e802b27 100644 --- a/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts @@ -355,6 +355,72 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "redirect_uris": { "type": "array", "items": { @@ -764,6 +830,72 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "redirect_uris": { "type": "array", "items": { @@ -1176,6 +1308,72 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "id_token_types_supported": { "anyOf": [ { @@ -1290,116 +1488,38 @@ export const DiscoveryMetadataPayloadSchemaObj = { "distributed" ] }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { + "FederationEntityMetadataPayload": { "type": "object", "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { + "federation_fetch_endpoint": { "type": "string" }, - "y": { + "federation_list_endpoint": { "type": "string" }, - "e": { + "federation_resolve_endpoint": { "type": "string" }, - "n": { + "federation_trust_mark_status_endpoint": { "type": "string" }, - "alg": { + "federation_trust_mark_list_endpoint": { "type": "string" }, - "d": { + "federation_trust_mark_endpoint": { "type": "string" }, - "dp": { + "federation_historical_keys_endpoint": { "type": "string" }, - "dq": { + "organization_name": { "type": "string" }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { + "homepage_uri": { "type": "string" } }, - "additionalProperties": {} + "additionalProperties": false }, "Format": { "type": "object", @@ -1531,6 +1651,117 @@ export const DiscoveryMetadataPayloadSchemaObj = { ], "additionalProperties": false }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} + }, "IdTokenType": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts index f3b2f432..eba69a3b 100644 --- a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts @@ -93,6 +93,72 @@ export const RPRegistrationMetadataPayloadSchemaObj = { {} ] }, + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_name": { "anyOf": [ { @@ -283,6 +349,150 @@ export const RPRegistrationMetadataPayloadSchemaObj = { "alg" ], "additionalProperties": false + }, + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false + }, + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { + "type": "string" + }, + "n": { + "type": "string" + }, + "alg": { + "type": "string" + }, + "d": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { + "type": "string" + } + }, + "additionalProperties": {} } } }; \ No newline at end of file diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 8648d9b4..21d3003f 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -276,6 +276,7 @@ interface DiscoveryMetadataCommonOpts { opPolicyUri?: string // from openid connect discovery 1_0 opTosUri?: string // from openid connect discovery 1_0 federationEntity?: FederationEntityMetadataOpts + openidCredentialVerifier: DynamicRegistrationClientMetadata & { vp_formats: Format } // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } @@ -383,6 +384,7 @@ interface DiscoveryMetadataCommonPayload { op_policy_uri?: string op_tos_uri?: string federation_entity?: FederationEntityMetadataPayload + openid_credential_verifier?: DynamicRegistrationClientMetadata & { vp_formats: Format } // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any @@ -423,6 +425,8 @@ export type RPRegistrationMetadataOpts = Partial< | 'subjectTypesSupported' | 'subject_syntax_types_supported' | 'vpFormatsSupported' + | 'federationEntity' + | 'openidCredentialVerifier' | 'clientName' | 'logo_uri' | 'tos_uri' @@ -443,6 +447,8 @@ export type RPRegistrationMetadataPayload = Pick< | 'subject_types_supported' | 'subject_syntax_types_supported' | 'vp_formats' + | 'federation_entity' + | 'openid_credential_verifier' | 'client_name' | 'logo_uri' | 'client_purpose' From 70893501363a63c9e9cd1b6e06d667683111f248 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 20 Nov 2024 16:28:07 +0100 Subject: [PATCH 04/60] chore: Added openid_credential_issuer. oauth_authorization_server and openid_wallet_provider into the client registration metadata --- .../lib/types/ServerMetadata.ts | 42 +- .../oid4vci-common/lib/types/v1_0_13.types.ts | 39 +- .../AuthorizationRequestPayloadVD11.schema.ts | 266 +++++------ ...ationRequestPayloadVD12OID4VPD18.schema.ts | 266 +++++------ ...ationRequestPayloadVD12OID4VPD20.schema.ts | 266 +++++------ .../AuthorizationRequestPayloadVID1.schema.ts | 266 +++++------ .../AuthorizationResponseOpts.schema.ts | 412 ++++-------------- .../DiscoveryMetadataPayload.schema.ts | 409 ++++------------- .../RPRegistrationMetadataPayload.schema.ts | 266 +++++------ packages/siop-oid4vp/lib/types/SIOP.types.ts | 66 +-- pnpm-lock.yaml | 16 +- 11 files changed, 948 insertions(+), 1366 deletions(-) diff --git a/packages/oid4vci-common/lib/types/ServerMetadata.ts b/packages/oid4vci-common/lib/types/ServerMetadata.ts index b8f6208c..4ff9c116 100644 --- a/packages/oid4vci-common/lib/types/ServerMetadata.ts +++ b/packages/oid4vci-common/lib/types/ServerMetadata.ts @@ -78,9 +78,43 @@ export type RevocationEndpointAuthSigningAlg = export type PKCECodeChallengeMethod = | 'plain' - | 'S256'; + | 'S256'; + +export interface FederationEntityMetadata { + federation_fetch_endpoint?: string; + federation_list_endpoint?: string; + federation_resolve_endpoint?: string; + federation_trust_mark_status_endpoint?: string; + federation_trust_mark_list_endpoint?: string; + federation_trust_mark_endpoint?: string; + federation_historical_keys_endpoint?: string; + organization_name?: string; + homepage_uri?: string; +} + +export interface JwtObject { + alg_values_supported?: Array +} + +export interface FormatSupported { + jwt?: JwtObject; + jwt_vc?: JwtObject; + jwt_vc_json?: JwtObject; + jwt_vp?: JwtObject; + jwt_vp_json?: JwtObject; +} + +export type WalletMetadata = { + presentation_definition_uri_supported?: boolean + vp_formats_supported?: FormatSupported +} + +export type OpenIDWalletProviderMetadata = { + federation_entity?: FederationEntityMetadata + openid_wallet_provider?: AuthorizationServerMetadata & WalletMetadata +} -export interface AuthorizationServerMetadata extends DynamicRegistrationClientMetadata { +export interface AuthorizationServerMetadata extends DynamicRegistrationClientMetadata, OpenIDWalletProviderMetadata { issuer: string; authorization_endpoint?: string; token_endpoint?: string; @@ -159,7 +193,9 @@ export const authorizationServerMetadataFieldNames: Array; // REQUIRED. A JSON object containing a list of key value pairs, where the key is a string serving as an abstract identifier of the Credential. This identifier is RECOMMENDED to be collision resistant - it can be globally unique, but does not have to be when naming conflicts are unlikely to arise in a given use case. The value is a JSON object. The JSON object MUST conform to the structure of the Section 11.2.1. credential_issuer: string; // A Credential Issuer is identified by a case sensitive URL using the https scheme that contains scheme, host and, optionally, port number and path components, but no query or fragment components. credential_endpoint: string; // REQUIRED. URL of the OP's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. @@ -189,19 +194,13 @@ export interface CredentialOfferPayloadV1_0_13 { client_id?: string; } -export interface FederationEntityMetadataOpts { - federation_fetch_endpoint?: string - federation_list_endpoint?: string - federation_resolve_endpoint?: string - federation_trust_mark_status_endpoint?: string - federation_trust_mark_list_endpoint?: string - federation_trust_mark_endpoint?: string - federation_historical_keys_endpoint?: string - organization_name?: string - homepage_uri?: string -} +export type OpenIDCredentialIssuer = { + federation_entity?: FederationEntityMetadata; + openid_credential_issuer?: DynamicRegistrationClientMetadata & { openid_credential_offer?: string }; + oauth_server_metadata?: AuthorizationServerMetadata +}; -export interface CredentialIssuerMetadataOptsV1_0_13 { +export interface CredentialIssuerMetadataOptsV1_0_13 extends OpenIDCredentialIssuer { credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. batch_credential_endpoint?: string; // OPTIONAL. URL of the Credential Issuer's Batch Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. If omitted, the Credential Issuer does not support the Batch Credential Endpoint. deferred_credential_endpoint?: string; // OPTIONAL. URL of the Credential Issuer's Deferred Credential Endpoint, as defined in Section 9. This URL MUST use the https scheme and MAY contain port, path, and query parameter components. If omitted, the Credential Issuer does not support the Deferred Credential Endpoint. @@ -217,7 +216,6 @@ export interface CredentialIssuerMetadataOptsV1_0_13 { //todo: these two are not mentioned in the spec token_endpoint?: string; credential_supplier_config?: CredentialSupplierConfig; - federation_entity?: FederationEntityMetadataOpts } // These can be used be a reducer @@ -240,9 +238,10 @@ export const credentialIssuerMetadataFieldNames: Array { +export interface CredentialIssuerMetadataV1_0_13 extends CredentialIssuerMetadataOptsV1_0_13 , Partial, OpenIDCredentialIssuer{ authorization_servers?: string[]; // OPTIONAL. Array of strings that identify the OAuth 2.0 Authorization Servers (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414]. credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components. credential_configurations_supported: Record; // REQUIRED. A JSON array containing a list of JSON objects, each of them representing metadata about a separate credential type that the Credential Issuer can issue. The JSON objects in the array MUST conform to the structure of the Section 10.2.3.1. diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts index f863fe85..f91f842e 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts @@ -122,6 +122,72 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "anyOf": [ { @@ -209,72 +275,6 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { {} ] }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_name": { "anyOf": [ { @@ -301,40 +301,38 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { } } }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false }, "Format": { "type": "object", @@ -466,39 +464,6 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { ], "additionalProperties": false }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false - }, "JWKS": { "type": "object", "properties": { @@ -610,6 +575,41 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { }, "additionalProperties": {} }, + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts index 70b075d6..5de0ba32 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts @@ -128,6 +128,72 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "anyOf": [ { @@ -215,72 +281,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { {} ] }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_name": { "anyOf": [ { @@ -307,40 +307,38 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { } } }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false }, "Format": { "type": "object", @@ -472,39 +470,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { ], "additionalProperties": false }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false - }, "JWKS": { "type": "object", "properties": { @@ -616,6 +581,41 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { }, "additionalProperties": {} }, + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts index efbd7209..2d706bdb 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts @@ -128,6 +128,72 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "anyOf": [ { @@ -215,72 +281,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { {} ] }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_name": { "anyOf": [ { @@ -307,40 +307,38 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { } } }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false }, "Format": { "type": "object", @@ -472,39 +470,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { ], "additionalProperties": false }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false - }, "JWKS": { "type": "object", "properties": { @@ -616,6 +581,41 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { }, "additionalProperties": {} }, + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts index c0573572..dcfda501 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts @@ -94,6 +94,72 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "anyOf": [ { @@ -181,72 +247,6 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { {} ] }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_name": { "anyOf": [ { @@ -273,40 +273,38 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { } } }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false }, "Format": { "type": "object", @@ -438,39 +436,6 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { ], "additionalProperties": false }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false - }, "JWKS": { "type": "object", "properties": { @@ -582,6 +547,41 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { }, "additionalProperties": {} }, + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] + }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index 0cb365d1..ffb4eee2 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -431,72 +431,6 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, - "federationEntity": { - "$ref": "#/definitions/FederationEntityMetadataOpts" - }, - "openidCredentialVerifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "type": "string" }, @@ -566,7 +500,6 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ - "openidCredentialVerifier", "passBy" ] }, @@ -933,72 +866,6 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, - "federationEntity": { - "$ref": "#/definitions/FederationEntityMetadataOpts" - }, - "openidCredentialVerifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "type": "string" }, @@ -1062,7 +929,6 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ - "openidCredentialVerifier", "passBy" ] }, @@ -1429,72 +1295,6 @@ export const AuthorizationResponseOptsSchemaObj = { "opTosUri": { "type": "string" }, - "federationEntity": { - "$ref": "#/definitions/FederationEntityMetadataOpts" - }, - "openidCredentialVerifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "idTokenTypesSupported": { "anyOf": [ { @@ -1513,7 +1313,6 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ - "openidCredentialVerifier", "passBy" ] } @@ -1650,38 +1449,116 @@ export const AuthorizationResponseOptsSchemaObj = { "distributed" ] }, - "FederationEntityMetadataOpts": { + "JWKS": { "type": "object", "properties": { - "federationFetchEndpoint": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { + "type": "object", + "properties": { + "kty": { "type": "string" }, - "federationListEndpoint": { + "crv": { "type": "string" }, - "federationResolveEndpoint": { + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "e": { "type": "string" }, - "federationTrustMarkStatusEndpoint": { + "n": { "type": "string" }, - "federationTrustMarkListEndpoint": { + "alg": { "type": "string" }, - "federationTrustMarkEndpoint": { + "d": { "type": "string" }, - "federationHistoricalKeysEndpoint": { + "dp": { "type": "string" }, - "organizationName": { + "dq": { "type": "string" }, - "homepageUri": { + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { "type": "string" } }, - "additionalProperties": false + "additionalProperties": {} }, "Format": { "type": "object", @@ -1813,117 +1690,6 @@ export const AuthorizationResponseOptsSchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, "IdTokenType": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts b/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts index 0e802b27..ba4f744b 100644 --- a/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/DiscoveryMetadataPayload.schema.ts @@ -355,72 +355,6 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "redirect_uris": { "type": "array", "items": { @@ -830,72 +764,6 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "redirect_uris": { "type": "array", "items": { @@ -1308,72 +1176,6 @@ export const DiscoveryMetadataPayloadSchemaObj = { "op_tos_uri": { "type": "string" }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "id_token_types_supported": { "anyOf": [ { @@ -1488,38 +1290,116 @@ export const DiscoveryMetadataPayloadSchemaObj = { "distributed" ] }, - "FederationEntityMetadataPayload": { + "JWKS": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JWK" + } + } + }, + "required": [ + "keys" + ], + "additionalProperties": false + }, + "JWK": { "type": "object", "properties": { - "federation_fetch_endpoint": { + "kty": { + "type": "string" + }, + "crv": { + "type": "string" + }, + "x": { "type": "string" }, - "federation_list_endpoint": { + "y": { "type": "string" }, - "federation_resolve_endpoint": { + "e": { "type": "string" }, - "federation_trust_mark_status_endpoint": { + "n": { "type": "string" }, - "federation_trust_mark_list_endpoint": { + "alg": { "type": "string" }, - "federation_trust_mark_endpoint": { + "d": { "type": "string" }, - "federation_historical_keys_endpoint": { + "dp": { "type": "string" }, - "organization_name": { + "dq": { "type": "string" }, - "homepage_uri": { + "ext": { + "type": "boolean" + }, + "k": { + "type": "string" + }, + "key_ops": { + "type": "array", + "items": { + "type": "string" + } + }, + "kid": { + "type": "string" + }, + "oth": { + "type": "array", + "items": { + "type": "object", + "properties": { + "d": { + "type": "string" + }, + "r": { + "type": "string" + }, + "t": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "qi": { + "type": "string" + }, + "use": { + "type": "string" + }, + "x5c": { + "type": "array", + "items": { + "type": "string" + } + }, + "x5t": { + "type": "string" + }, + "x5t#S256": { + "type": "string" + }, + "x5u": { "type": "string" } }, - "additionalProperties": false + "additionalProperties": {} }, "Format": { "type": "object", @@ -1651,117 +1531,6 @@ export const DiscoveryMetadataPayloadSchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, "IdTokenType": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts index eba69a3b..3d2b5028 100644 --- a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts @@ -6,6 +6,72 @@ export const RPRegistrationMetadataPayloadSchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { + "federation_entity": { + "$ref": "#/definitions/FederationEntityMetadataPayload" + }, + "openid_credential_verifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "vp_formats": { + "$ref": "#/definitions/Format" + }, + "redirect_uris": { + "type": "array", + "items": { + "type": "string" + } + }, + "token_endpoint_auth_method": { + "type": "string" + }, + "grant_types": { + "type": "string" + }, + "response_types": { + "type": "string" + }, + "client_name": { + "type": "string" + }, + "client_uri": { + "type": "string" + }, + "logo_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "contacts": { + "type": "array", + "items": { + "type": "string" + } + }, + "tos_uri": { + "type": "string" + }, + "policy_uri": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "jwks": { + "$ref": "#/definitions/JWKS" + }, + "software_id": { + "type": "string" + }, + "software_version": { + "type": "string" + } + }, + "required": [ + "vp_formats" + ] + }, "client_id": { "anyOf": [ { @@ -93,72 +159,6 @@ export const RPRegistrationMetadataPayloadSchemaObj = { {} ] }, - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_name": { "anyOf": [ { @@ -185,40 +185,38 @@ export const RPRegistrationMetadataPayloadSchemaObj = { } } }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] + "FederationEntityMetadataPayload": { + "type": "object", + "properties": { + "federation_fetch_endpoint": { + "type": "string" + }, + "federation_list_endpoint": { + "type": "string" + }, + "federation_resolve_endpoint": { + "type": "string" + }, + "federation_trust_mark_status_endpoint": { + "type": "string" + }, + "federation_trust_mark_list_endpoint": { + "type": "string" + }, + "federation_trust_mark_endpoint": { + "type": "string" + }, + "federation_historical_keys_endpoint": { + "type": "string" + }, + "organization_name": { + "type": "string" + }, + "homepage_uri": { + "type": "string" + } + }, + "additionalProperties": false }, "Format": { "type": "object", @@ -350,39 +348,6 @@ export const RPRegistrationMetadataPayloadSchemaObj = { ], "additionalProperties": false }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false - }, "JWKS": { "type": "object", "properties": { @@ -493,6 +458,41 @@ export const RPRegistrationMetadataPayloadSchemaObj = { } }, "additionalProperties": {} + }, + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] } } }; \ No newline at end of file diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 21d3003f..51527b3b 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -1,6 +1,10 @@ // noinspection JSUnusedGlobalSymbols import { JarmClientMetadata } from '@sphereon/jarm' -import { DynamicRegistrationClientMetadata, JWKS, SigningAlgo } from '@sphereon/oid4vc-common' +import { + DynamicRegistrationClientMetadata, + JWKS, + SigningAlgo +} from '@sphereon/oid4vc-common' import { Format, PresentationDefinitionV1, PresentationDefinitionV2 } from '@sphereon/pex-models' import { AdditionalClaims, @@ -11,22 +15,28 @@ import { PresentationSubmission, W3CVerifiableCredential, W3CVerifiablePresentation, - WrappedVerifiablePresentation, + WrappedVerifiablePresentation } from '@sphereon/ssi-types' -import { AuthorizationRequest, CreateAuthorizationRequestOpts, PropertyTargets, VerifyAuthorizationRequestOpts } from '../authorization-request' +import { + AuthorizationRequest, + CreateAuthorizationRequestOpts, + PropertyTargets, + VerifyAuthorizationRequestOpts +} from '../authorization-request' import { AuthorizationResponse, AuthorizationResponseOpts, PresentationDefinitionWithLocation, PresentationVerificationCallback, - VerifyAuthorizationResponseOpts, + VerifyAuthorizationResponseOpts } from '../authorization-response' -import { JwksMetadataParams } from '../helpers/ExtractJwks' +import { JwksMetadataParams } from '../helpers' import { RequestObject, RequestObjectOpts } from '../request-object' import { IRPSessionManager } from '../rp' import { JWTPayload, VerifiedJWT } from './index' + export const DEFAULT_EXPIRATION_TIME = 10 * 60 // https://openid.net/specs/openid-connect-core-1_0.html#RequestObject @@ -220,6 +230,18 @@ export interface RequestStateInfo { iat?: number } +export interface FederationEntityMetadataPayload { + federation_fetch_endpoint?: string + federation_list_endpoint?: string + federation_resolve_endpoint?: string + federation_trust_mark_status_endpoint?: string + federation_trust_mark_list_endpoint?: string + federation_trust_mark_endpoint?: string + federation_historical_keys_endpoint?: string + organization_name?: string + homepage_uri?: string +} + export interface FederationEntityMetadataOpts { federationFetchEndpoint?: string federationListEndpoint?: string @@ -232,6 +254,16 @@ export interface FederationEntityMetadataOpts { homepageUri?: string } +export type OpenIDCredentialVerifierOpts = { + federationEntity?: FederationEntityMetadataOpts; + openidCredentialVerifier?: DynamicRegistrationClientMetadata & { vp_formats: Format }; +}; + +export type OpenIDCredentialVerifierPayload = { + federation_entity?: FederationEntityMetadataPayload; + openid_credential_verifier?: DynamicRegistrationClientMetadata & { vp_formats: Format }; +}; + interface DiscoveryMetadataCommonOpts { //TODO add the check: Mandatory if PassBy.Value authorizationEndpoint?: Schema | string @@ -275,8 +307,6 @@ interface DiscoveryMetadataCommonOpts { requireRequestUriRegistration?: boolean // from openid connect discovery 1_0 opPolicyUri?: string // from openid connect discovery 1_0 opTosUri?: string // from openid connect discovery 1_0 - federationEntity?: FederationEntityMetadataOpts - openidCredentialVerifier: DynamicRegistrationClientMetadata & { vp_formats: Format } // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } @@ -312,18 +342,6 @@ interface DiscoveryMetadataOptsVD11 extends DiscoveryMetadataCommonOpts { vpFormatsSupported?: Format // from oidc4vp } -export interface FederationEntityMetadataPayload { - federation_fetch_endpoint?: string - federation_list_endpoint?: string - federation_resolve_endpoint?: string - federation_trust_mark_status_endpoint?: string - federation_trust_mark_list_endpoint?: string - federation_trust_mark_endpoint?: string - federation_historical_keys_endpoint?: string - organization_name?: string - homepage_uri?: string -} - // https://openid.net/specs/openid-connect-self-issued-v2-1_0.html#section-8.2 // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata interface DiscoveryMetadataCommonPayload { @@ -383,8 +401,6 @@ interface DiscoveryMetadataCommonPayload { require_request_uri_registration?: boolean op_policy_uri?: string op_tos_uri?: string - federation_entity?: FederationEntityMetadataPayload - openid_credential_verifier?: DynamicRegistrationClientMetadata & { vp_formats: Format } // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any @@ -425,14 +441,12 @@ export type RPRegistrationMetadataOpts = Partial< | 'subjectTypesSupported' | 'subject_syntax_types_supported' | 'vpFormatsSupported' - | 'federationEntity' - | 'openidCredentialVerifier' | 'clientName' | 'logo_uri' | 'tos_uri' | 'clientPurpose' > -> & { +> & OpenIDCredentialVerifierOpts & { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } @@ -447,12 +461,10 @@ export type RPRegistrationMetadataPayload = Pick< | 'subject_types_supported' | 'subject_syntax_types_supported' | 'vp_formats' - | 'federation_entity' - | 'openid_credential_verifier' | 'client_name' | 'logo_uri' | 'client_purpose' -> & { +> & OpenIDCredentialVerifierPayload & { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7378a309..a3eb2823 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,7 +76,7 @@ importers: version: link:../issuer '@sphereon/ssi-types': specifier: 0.30.1 - version: 0.30.1(encoding@0.1.13)(ts-node@10.9.2(@types/node@18.19.54)(typescript@5.4.5)) + version: 0.30.1(encoding@0.1.13)(ts-node@10.9.2(@types/node@18.19.54)(typescript@5.5.3)) jose: specifier: ^4.10.0 version: 4.15.9 @@ -129,7 +129,7 @@ importers: devDependencies: '@sphereon/ssi-sdk-ext.key-utils': specifier: ^0.23.0 - version: 0.23.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1) + version: 0.23.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1))) '@transmute/did-key.js': specifier: ^0.3.0-unstable.10 version: 0.3.0-unstable.10(encoding@0.1.13) @@ -10164,7 +10164,7 @@ snapshots: '@digitalcredentials/bnid@2.1.2(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1))': dependencies: '@digitalcredentials/base58-universal': 1.0.1 - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)) yargs: 15.4.1 transitivePeerDependencies: - react-native @@ -11982,7 +11982,7 @@ snapshots: transitivePeerDependencies: - encoding - '@sphereon/isomorphic-webcrypto@2.4.1-unstable.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1)': + '@sphereon/isomorphic-webcrypto@2.4.1-unstable.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)))': dependencies: '@peculiar/webcrypto': 1.5.0 asmcrypto.js: 2.3.2 @@ -12000,7 +12000,7 @@ snapshots: webcrypto-shim: 0.1.7 optionalDependencies: expo: 48.0.21(@babel/core@7.25.2)(encoding@0.1.13) - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)) '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': dependencies: @@ -12264,10 +12264,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@sphereon/ssi-sdk-ext.key-utils@0.23.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1)': + '@sphereon/ssi-sdk-ext.key-utils@0.23.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)))': dependencies: '@ethersproject/random': 5.7.0 - '@sphereon/isomorphic-webcrypto': 2.4.1-unstable.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1) + '@sphereon/isomorphic-webcrypto': 2.4.1-unstable.0(expo@48.0.21(@babel/core@7.25.2)(encoding@0.1.13))(msrcrypto@1.5.8)(react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1))) '@stablelib/ed25519': 1.0.3 '@stablelib/sha256': 1.0.1 '@stablelib/sha512': 1.0.1 @@ -18726,7 +18726,7 @@ snapshots: react-native: 0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1) optional: true - react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)): + react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)): dependencies: base64-js: 1.5.1 react-native: 0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1) From dc1c318fa130dc7fec493b82f69a1f563f62713c Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Thu, 21 Nov 2024 08:31:10 +0100 Subject: [PATCH 05/60] feat: dcql alpha --- .../AuthorizationResponse.ts | 19 ++++-- .../lib/authorization-response/Dcql.ts | 20 +++--- .../lib/authorization-response/OpenID4VP.ts | 62 +++++++++++-------- .../lib/authorization-response/Payload.ts | 6 +- .../lib/authorization-response/types.ts | 6 +- packages/siop-oid4vp/lib/rp/RP.ts | 6 +- ...ationRequestPayloadVD12OID4VPD20.schema.ts | 3 + .../AuthorizationRequestPayloadVID1.schema.ts | 3 + .../AuthorizationResponseOpts.schema.ts | 26 ++++++++ packages/siop-oid4vp/lib/types/SIOP.types.ts | 7 +++ 10 files changed, 111 insertions(+), 47 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index de5f1b3a..df4d1288 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -1,4 +1,4 @@ -import { CredentialMapper, Hasher } from '@sphereon/ssi-types' +import { CredentialMapper, Hasher, WrappedVerifiablePresentation } from '@sphereon/ssi-types' import { AuthorizationRequest, VerifyAuthorizationRequestOpts } from '../authorization-request' import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-request/Opts' @@ -11,6 +11,7 @@ import { extractPresentationsFromVpToken, verifyPresentations, } from './OpenID4VP' +import { extractPresentationsFromDcqlVpToken } from './OpenID4VP' import { assertValidResponseOpts } from './Opts' import { createResponsePayload } from './Payload' import { AuthorizationResponseOpts, PresentationDefinitionWithLocation, VerifyAuthorizationResponseOpts } from './types' @@ -141,7 +142,7 @@ export class AuthorizationResponse { }, }) } else { - throw new Error('TODO: VALIDATE PRESENTATION AGAINST DEFINITION') + console.error('TODO: VALIDATE PRESENTATION AGAINST DEFINITION') } } @@ -189,7 +190,8 @@ export class AuthorizationResponse { state, correlationId: verifyOpts.correlationId, ...(this.idToken && { idToken: verifiedIdToken }), - ...(oid4vp && { oid4vpSubmission: oid4vp }), + ...(oid4vp && 'presentationDefinitions' in oid4vp && { oid4vpSubmission: oid4vp }), + ...(oid4vp && 'dcqlQuery' in oid4vp && { oid4vpSubmissionDcql: oid4vp }), } } @@ -217,8 +219,15 @@ export class AuthorizationResponse { public async mergedPayloads(opts?: { consistencyCheck?: boolean; hasher?: Hasher }): Promise { let nonce: string | undefined = this._payload.nonce if (this._payload?.vp_token) { - const presentations = this.payload.vp_token ? await extractPresentationsFromVpToken(this.payload.vp_token, opts) : [] - if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) { + let presentations: WrappedVerifiablePresentation | WrappedVerifiablePresentation[] + + try { + presentations = extractPresentationsFromDcqlVpToken(this._payload.vp_token as string, opts) + } catch (e) { + presentations = extractPresentationsFromVpToken(this._payload.vp_token, opts) + } + + if (presentations && Array.isArray(presentations) && presentations.length === 0) { return Promise.reject(Error('missing presentation(s)')) } const presentationsArray = Array.isArray(presentations) ? presentations : [presentations] diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index e67fb783..16cf9672 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -11,8 +11,8 @@ import { AuthorizationRequestPayload, SIOPErrors } from '../types' * @param version */ export const findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise => { - const vpTokens: string[] = extractDataFromPath(authorizationRequestPayload, '$..vp_token.dcql_query').map((d) => d.value) - const vpTokensList: string[] = extractDataFromPath(authorizationRequestPayload, '$..vp_token.dcql_query[*]').map((d) => d.value) + const dcqlQuery: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query').map((d) => d.value) + const dcqlQueryList: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query[*]').map((d) => d.value) const definitions = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition') const definitionsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition[*]') const definitionRefs = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri') @@ -20,25 +20,21 @@ export const findValidDcqlQuery = async (authorizationRequestPayload: Authorizat const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) - const hasDcql = (vpTokens && vpTokens.length > 0) || (vpTokensList && vpTokensList.length > 0) + const hasDcql = (dcqlQuery && dcqlQuery.length > 0) || (dcqlQueryList && dcqlQueryList.length > 0) if ([hasPD, hasPdRef, hasDcql].filter(Boolean).length > 1) { throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) } - if (!(vpTokens && vpTokens.length) && !(vpTokensList && vpTokensList.length)) { - throw new Error('Cannot find dcql_query in vp_token. Presentation definition is present') - } - - if (vpTokens.length > 1 && vpTokensList.length > 1) { + if (dcqlQuery.length > 1 || dcqlQueryList.length > 1) { throw new Error('Found multiple dcql_query in vp_token. Only one is allowed') } - const encoded = vpTokens.length ? vpTokens[0] : vpTokensList[0] + const encoded = dcqlQuery.length ? dcqlQuery[0] : dcqlQueryList[0] if (!encoded) return undefined - const dcqlQuery = DcqlQuery.parse(JSON.parse(encoded)) - DcqlQuery.validate(dcqlQuery) + const parsedDcqlQuery = DcqlQuery.parse(JSON.parse(encoded)) + DcqlQuery.validate(parsedDcqlQuery) - return dcqlQuery + return parsedDcqlQuery } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index ec76bd4d..4ff909cf 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -10,7 +10,7 @@ import { W3CVerifiablePresentation, WrappedVerifiablePresentation, } from '@sphereon/ssi-types' -import { DcqlQuery, DcqlQueryVpToken } from 'dcql' +import { DcqlQuery, DcqlVpToken } from 'dcql' import { AuthorizationRequest } from '../authorization-request' import { verifyRevocation } from '../helpers' @@ -22,6 +22,7 @@ import { SIOPErrors, SupportedVersion, VerifiedOpenID4VPSubmission, + VerifiedOpenID4VPSubmissionDcql, } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' @@ -70,10 +71,12 @@ export const extractNonceFromWrappedVerifiablePresentation = (wrappedVp: Wrapped export const verifyPresentations = async ( authorizationResponse: AuthorizationResponse, verifyOpts: VerifyAuthorizationResponseOpts, -): Promise => { +): Promise => { + if (!authorizationResponse.payload.vp_token) return null if ( - !authorizationResponse.payload.vp_token || - (Array.isArray(authorizationResponse.payload.vp_token) && authorizationResponse.payload.vp_token.length === 0) + authorizationResponse.payload.vp_token && + Array.isArray(authorizationResponse.payload.vp_token) && + authorizationResponse.payload.vp_token.length === 0 ) { return Promise.reject(Error('the payload is missing a vp_token')) } @@ -83,9 +86,6 @@ export const verifyPresentations = async ( idPayload = await authorizationResponse.idToken.payload() } - // todo: Probably wise to check against request for the location of the submission_data - const presentationSubmission = idPayload?._vp_token?.presentation_submission ?? authorizationResponse.payload.presentation_submission - let wrappedPresentations: WrappedVerifiablePresentation[] = [] const presentationDefinitions = verifyOpts.presentationDefinitions ? Array.isArray(verifyOpts.presentationDefinitions) @@ -93,18 +93,19 @@ export const verifyPresentations = async ( : [verifyOpts.presentationDefinitions] : [] - const dcqlQuery = verifyOpts.dcqlQuery ?? authorizationResponse.authorizationRequest.payload.dcql_query - if (dcqlQuery) { - const dcqlQueryVpToken = DcqlQueryVpToken.parse(JSON.parse(authorizationResponse.payload.vp_token as string)) + let presentationSubmission: PresentationSubmission | undefined - const parsedQuery = DcqlQuery.parse(dcqlQuery) - DcqlQuery.validate(parsedQuery) + let dcqlQuery = verifyOpts.dcqlQuery ?? authorizationResponse?.authorizationRequest?.payload.dcql_query + if (dcqlQuery) { + dcqlQuery = DcqlQuery.parse(dcqlQuery) + DcqlQuery.validate(dcqlQuery) - const presentations = Object.values(dcqlQueryVpToken) as Array - wrappedPresentations = presentations.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: verifyOpts.hasher })) + wrappedPresentations = extractPresentationsFromDcqlVpToken(authorizationResponse.payload.vp_token as string, { hasher: verifyOpts.hasher }) const verifiedPresentations = await Promise.all( - presentations.map((presentation) => verifyOpts.verification.presentationVerificationCallback(presentation, presentationSubmission)), + wrappedPresentations.map((presentation) => + verifyOpts.verification.presentationVerificationCallback(presentation.original as W3CVerifiablePresentation), + ), ) // TODO: assert the submission against the definition @@ -118,9 +119,14 @@ export const verifyPresentations = async ( throw Error(`Failed to verify presentations. ${message}`) } } else { - const presentations = await extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) + const presentations = authorizationResponse.payload.vp_token + ? await extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) + : [] wrappedPresentations = Array.isArray(presentations) ? presentations : [presentations] + // todo: Probably wise to check against request for the location of the submission_data + presentationSubmission = idPayload?._vp_token?.presentation_submission ?? authorizationResponse.payload.presentation_submission + await assertValidVerifiablePresentations({ presentationDefinitions, presentations, @@ -134,12 +140,6 @@ export const verifyPresentations = async ( }) } - // If there are no presentations, and the `assertValidVerifiablePresentations` did not fail - // it means there's no oid4vp response and also not requested - if (wrappedPresentations.length === 0) { - return null - } - const presentationsWithoutMdoc = wrappedPresentations.filter((p) => p.format !== 'mso_mdoc') const nonces = new Set(presentationsWithoutMdoc.map(extractNonceFromWrappedVerifiablePresentation)) if (presentationsWithoutMdoc.length > 0 && nonces.size !== 1) { @@ -163,13 +163,25 @@ export const verifyPresentations = async ( await verifyRevocation(vp, verifyOpts.verification.revocationOpts.revocationVerificationCallback, revocationVerification) } } - return { nonce, presentations: wrappedPresentations, presentationDefinitions, submissionData: presentationSubmission } + if (presentationDefinitions) { + return { nonce, presentations: wrappedPresentations, presentationDefinitions, submissionData: presentationSubmission } + } else { + return { nonce, presentations: wrappedPresentations, dcqlQuery } + } +} + +export const extractPresentationsFromDcqlVpToken = ( + vpToken: DcqlVpToken.Input | string, + opts?: { hasher?: Hasher }, +): WrappedVerifiablePresentation[] => { + const presentations = Object.values(DcqlVpToken.parse(vpToken)) as Array + return presentations.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: opts.hasher })) } -export const extractPresentationsFromVpToken = async ( +export const extractPresentationsFromVpToken = ( vpToken: Array | W3CVerifiablePresentation | CompactSdJwtVc | string, opts?: { hasher?: Hasher }, -): Promise => { +): WrappedVerifiablePresentation[] | WrappedVerifiablePresentation => { const tokens = Array.isArray(vpToken) ? vpToken : [vpToken] const wrappedTokens = tokens.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: opts?.hasher })) diff --git a/packages/siop-oid4vp/lib/authorization-response/Payload.ts b/packages/siop-oid4vp/lib/authorization-response/Payload.ts index bdd7cc80..286c3705 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Payload.ts @@ -28,7 +28,11 @@ export const createResponsePayload = async ( } // vp tokens - await putPresentationSubmissionInLocation(authorizationRequest, responsePayload, responseOpts, idTokenPayload) + if (responseOpts.dcqlQuery) { + responsePayload.vp_token = JSON.stringify(responseOpts.dcqlQuery.credentialQueryIdToPresentation) + } else { + await putPresentationSubmissionInLocation(authorizationRequest, responsePayload, responseOpts, idTokenPayload) + } if (idTokenPayload) { const idToken = await IDToken.fromIDTokenPayload(idTokenPayload, responseOpts) responsePayload.id_token = await idToken.jwt(responseOpts.jwtIssuer) diff --git a/packages/siop-oid4vp/lib/authorization-response/types.ts b/packages/siop-oid4vp/lib/authorization-response/types.ts index 9a6e1bf2..944e0296 100644 --- a/packages/siop-oid4vp/lib/authorization-response/types.ts +++ b/packages/siop-oid4vp/lib/authorization-response/types.ts @@ -9,7 +9,7 @@ import { PresentationSubmission, W3CVerifiablePresentation, } from '@sphereon/ssi-types' -import { DcqlQuery, DcqlQueryVpToken } from 'dcql' +import { DcqlQuery } from 'dcql' import { ResponseMode, @@ -62,7 +62,7 @@ export interface PresentationExchangeResponseOpts { } export interface DcqlQueryResponseOpts { - credentialQueryIdToPresentation: DcqlQueryVpToken + credentialQueryIdToPresentation: Record | string> } export interface PresentationExchangeRequestOpts { @@ -108,7 +108,7 @@ export type PresentationVerificationResult = { verified: boolean; reason?: strin export type PresentationVerificationCallback = ( args: W3CVerifiablePresentation | CompactSdJwtVc | MdocOid4vpIssuerSigned, - presentationSubmission: PresentationSubmission, + presentationSubmission?: PresentationSubmission, ) => Promise export type PresentationSignCallback = (args: PresentationSignCallBackParams) => Promise diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index addc9a23..827db4c4 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -22,6 +22,7 @@ import { import { mergeVerificationOpts } from '../authorization-request/Opts' import { AuthorizationResponse, + extractPresentationsFromDcqlVpToken, extractPresentationsFromVpToken, PresentationDefinitionWithLocation, VerifyAuthorizationResponseOpts, @@ -169,7 +170,10 @@ export class RP { }, ) - const presentations = await extractPresentationsFromVpToken(validatedResponse.authResponseParams.vp_token, { hasher }) + const presentations = validatedResponse.authRequestParams.dcql_query + ? extractPresentationsFromDcqlVpToken(validatedResponse.authResponseParams.vp_token as string, { hasher }) + : extractPresentationsFromVpToken(validatedResponse.authResponseParams.vp_token, { hasher }) + const mdocVerifiablePresentations = (Array.isArray(presentations) ? presentations : [presentations]).filter((p) => p.format === 'mso_mdoc') if (mdocVerifiablePresentations.length) { diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts index 42961fb7..e740951a 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts @@ -122,6 +122,9 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { }, "response_uri": { "type": "string" + }, + "dcql_query": { + "type": "string" } } }, diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts index 0b78c774..59cc00bf 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts @@ -414,6 +414,9 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { }, "presentation_definition_uri": { "type": "string" + }, + "dcql_query": { + "type": "string" } }, "additionalProperties": false diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index ffb4eee2..f4665713 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -52,6 +52,9 @@ export const AuthorizationResponseOptsSchemaObj = { }, "presentationExchange": { "$ref": "#/definitions/PresentationExchangeResponseOpts" + }, + "dcqlQuery": { + "$ref": "#/definitions/DcqlQueryResponseOpts" } }, "required": [ @@ -2335,6 +2338,29 @@ export const AuthorizationResponseOptsSchemaObj = { "id_token", "token_response" ] + }, + "DcqlQueryResponseOpts": { + "type": "object", + "properties": { + "credentialQueryIdToPresentation": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "object", + "additionalProperties": {} + }, + { + "type": "string" + } + ] + } + } + }, + "required": [ + "credentialQueryIdToPresentation" + ], + "additionalProperties": false } } }; \ No newline at end of file diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 30619c0f..3933216e 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -516,6 +516,12 @@ export interface VerifiedIDToken { verifyOpts: VerifyAuthorizationResponseOpts } +export interface VerifiedOpenID4VPSubmissionDcql { + dcqlQuery: DcqlQuery + presentations: WrappedVerifiablePresentation[] + nonce?: string +} + export interface VerifiedOpenID4VPSubmission { submissionData: PresentationSubmission presentationDefinitions: PresentationDefinitionWithLocation[] @@ -529,6 +535,7 @@ export interface VerifiedAuthorizationResponse { authorizationResponse: AuthorizationResponse oid4vpSubmission?: VerifiedOpenID4VPSubmission + oid4vpSubmissionDcql?: VerifiedOpenID4VPSubmissionDcql nonce?: string state: string From 6ff33553305bf59f7a55259ab7d63ae5398c37fa Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Thu, 21 Nov 2024 09:09:09 +0100 Subject: [PATCH 06/60] fix: dcql alpha --- .../__tests__/PresentationExchange.spec.ts | 4 +-- .../AuthorizationResponse.ts | 23 ++++++++++-- .../lib/authorization-response/Dcql.ts | 33 +++++++++++------ .../lib/authorization-response/OpenID4VP.ts | 35 ++++++++++--------- .../lib/authorization-response/Payload.ts | 4 ++- .../lib/authorization-response/types.ts | 6 +--- .../AuthorizationResponseOpts.schema.ts | 4 +-- packages/siop-oid4vp/lib/types/SIOP.types.ts | 4 +-- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 25 +++++++++++-- 10 files changed, 95 insertions(+), 45 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/PresentationExchange.spec.ts b/packages/siop-oid4vp/lib/__tests__/PresentationExchange.spec.ts index 8d69fd5b..5f907d40 100644 --- a/packages/siop-oid4vp/lib/__tests__/PresentationExchange.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/PresentationExchange.spec.ts @@ -337,9 +337,7 @@ describe('presentation exchange manager tests', () => { const payload = await getPayloadVID1Val() // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(payload.claims?.vp_token as any).presentation_definition_uri = EXAMPLE_PD_URL - await expect(PresentationExchange.findValidPresentationDefinitions(payload)).rejects.toThrow( - SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_BY_REF_AND_VALUE_NON_EXCLUSIVE, - ) + await expect(PresentationExchange.findValidPresentationDefinitions(payload)).rejects.toThrow(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) }) it('validatePresentationAgainstDefinition: should pass if provided VP match the PD', async function () { diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index df4d1288..8e64938f 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -1,10 +1,12 @@ import { CredentialMapper, Hasher, WrappedVerifiablePresentation } from '@sphereon/ssi-types' +import { DcqlPresentationRecord } from 'dcql' import { AuthorizationRequest, VerifyAuthorizationRequestOpts } from '../authorization-request' import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-request/Opts' import { IDToken } from '../id-token' import { AuthorizationResponsePayload, ResponseType, SIOPErrors, VerifiedAuthorizationRequest, VerifiedAuthorizationResponse } from '../types' +import { assertValidDcqlPresentationRecrod } from './Dcql' import { assertValidVerifiablePresentations, extractNonceFromWrappedVerifiablePresentation, @@ -142,7 +144,13 @@ export class AuthorizationResponse { }, }) } else { - console.error('TODO: VALIDATE PRESENTATION AGAINST DEFINITION') + const dcqlQuery = verifiedAuthorizationRequest.dcqlQuery + if (!dcqlQuery) { + throw new Error('vp_token is present, but no presentation definitions or dcql query provided') + } + assertValidDcqlPresentationRecrod(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord, dcqlQuery, { + hasher: verifyOpts.hasher, + }) } } @@ -160,7 +168,16 @@ export class AuthorizationResponse { } const verifiedIdToken = await this.idToken?.verify(verifyOpts) - const oid4vp = await verifyPresentations(this, verifyOpts) + if (this.payload.vp_token && !verifyOpts.presentationDefinitions && !verifyOpts.dcqlQuery) { + throw Promise.reject(Error('vp_token is present, but no presentation definitions or dcql query provided')) + } + + const emptyPresentationDefinitions = Array.isArray(verifyOpts.presentationDefinitions) && verifyOpts.presentationDefinitions.length === 0 + if (!this.payload.vp_token && ((verifyOpts.presentationDefinitions && !emptyPresentationDefinitions) || verifyOpts.dcqlQuery)) { + throw Promise.reject(Error('Presentation definitions or dcql query provided, but no vp_token present')) + } + + const oid4vp = this.payload.vp_token ? await verifyPresentations(this, verifyOpts) : undefined // Gather all nonces const allNonces = new Set() @@ -227,7 +244,7 @@ export class AuthorizationResponse { presentations = extractPresentationsFromVpToken(this._payload.vp_token, opts) } - if (presentations && Array.isArray(presentations) && presentations.length === 0) { + if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) { return Promise.reject(Error('missing presentation(s)')) } const presentationsArray = Array.isArray(presentations) ? presentations : [presentations] diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index 16cf9672..b2488e2e 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -1,8 +1,11 @@ -import { DcqlQuery } from 'dcql' +import { Hasher } from '@sphereon/ssi-types' +import { DcqlMdocRepresentation, DcqlPresentationRecord, DcqlQuery, DcqlSdJwtVcRepresentation } from 'dcql' import { extractDataFromPath } from '../helpers' import { AuthorizationRequestPayload, SIOPErrors } from '../types' +import { extractPresentationRecordFromDcqlVpToken } from './OpenID4VP' + /** * Finds a valid DcqlQuery inside the given AuthenticationRequestPayload * throws exception if the DcqlQuery is not valid @@ -12,7 +15,6 @@ import { AuthorizationRequestPayload, SIOPErrors } from '../types' */ export const findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise => { const dcqlQuery: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query').map((d) => d.value) - const dcqlQueryList: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query[*]').map((d) => d.value) const definitions = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition') const definitionsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition[*]') const definitionRefs = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri') @@ -20,21 +22,32 @@ export const findValidDcqlQuery = async (authorizationRequestPayload: Authorizat const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) - const hasDcql = (dcqlQuery && dcqlQuery.length > 0) || (dcqlQueryList && dcqlQueryList.length > 0) + const hasDcql = dcqlQuery && dcqlQuery.length > 0 if ([hasPD, hasPdRef, hasDcql].filter(Boolean).length > 1) { throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) } - if (dcqlQuery.length > 1 || dcqlQueryList.length > 1) { + if (dcqlQuery.length === 0) return undefined + + if (dcqlQuery.length > 1) { throw new Error('Found multiple dcql_query in vp_token. Only one is allowed') } - const encoded = dcqlQuery.length ? dcqlQuery[0] : dcqlQueryList[0] - if (!encoded) return undefined - - const parsedDcqlQuery = DcqlQuery.parse(JSON.parse(encoded)) - DcqlQuery.validate(parsedDcqlQuery) + return DcqlQuery.parse(JSON.parse(dcqlQuery[0])) +} - return parsedDcqlQuery +export const assertValidDcqlPresentationRecrod = async (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { + const wrappedPresentations = Object.values(extractPresentationRecordFromDcqlVpToken(record, opts)) + const credentials = wrappedPresentations.map((p) => { + if (p.format === 'mso_mdoc') { + return { docType: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocRepresentation + } else if (p.format === 'vc+sd-jwt') { + return { vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcRepresentation + } else { + throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') + } + }) + + DcqlPresentationRecord.validate(credentials, { dcqlQuery }) } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 4ff909cf..d1a4e72e 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -10,7 +10,7 @@ import { W3CVerifiablePresentation, WrappedVerifiablePresentation, } from '@sphereon/ssi-types' -import { DcqlQuery, DcqlVpToken } from 'dcql' +import { DcqlPresentationRecord, DcqlQuery } from 'dcql' import { AuthorizationRequest } from '../authorization-request' import { verifyRevocation } from '../helpers' @@ -26,6 +26,7 @@ import { } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' +import { assertValidDcqlPresentationRecrod } from './Dcql' import { PresentationExchange } from './PresentationExchange' import { AuthorizationResponseOpts, @@ -72,15 +73,6 @@ export const verifyPresentations = async ( authorizationResponse: AuthorizationResponse, verifyOpts: VerifyAuthorizationResponseOpts, ): Promise => { - if (!authorizationResponse.payload.vp_token) return null - if ( - authorizationResponse.payload.vp_token && - Array.isArray(authorizationResponse.payload.vp_token) && - authorizationResponse.payload.vp_token.length === 0 - ) { - return Promise.reject(Error('the payload is missing a vp_token')) - } - let idPayload: IDTokenPayload | undefined if (authorizationResponse.idToken) { idPayload = await authorizationResponse.idToken.payload() @@ -98,8 +90,6 @@ export const verifyPresentations = async ( let dcqlQuery = verifyOpts.dcqlQuery ?? authorizationResponse?.authorizationRequest?.payload.dcql_query if (dcqlQuery) { dcqlQuery = DcqlQuery.parse(dcqlQuery) - DcqlQuery.validate(dcqlQuery) - wrappedPresentations = extractPresentationsFromDcqlVpToken(authorizationResponse.payload.vp_token as string, { hasher: verifyOpts.hasher }) const verifiedPresentations = await Promise.all( @@ -108,7 +98,7 @@ export const verifyPresentations = async ( ), ) - // TODO: assert the submission against the definition + assertValidDcqlPresentationRecrod(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) if (verifiedPresentations.some((verified) => !verified)) { const message = verifiedPresentations @@ -170,12 +160,25 @@ export const verifyPresentations = async ( } } +export const extractPresentationRecordFromDcqlVpToken = ( + vpToken: DcqlPresentationRecord.Input | string, + opts?: { hasher?: Hasher }, +): Record => { + const presentationRecord = Object.fromEntries( + Object.entries(DcqlPresentationRecord.parse(vpToken)).map(([credentialQueryId, vp]) => [ + credentialQueryId, + CredentialMapper.toWrappedVerifiablePresentation(vp as W3CVerifiablePresentation | CompactSdJwtVc | string, { hasher: opts.hasher }), + ]), + ) + + return presentationRecord +} + export const extractPresentationsFromDcqlVpToken = ( - vpToken: DcqlVpToken.Input | string, + vpToken: DcqlPresentationRecord.Input | string, opts?: { hasher?: Hasher }, ): WrappedVerifiablePresentation[] => { - const presentations = Object.values(DcqlVpToken.parse(vpToken)) as Array - return presentations.map((vp) => CredentialMapper.toWrappedVerifiablePresentation(vp, { hasher: opts.hasher })) + return Object.values(extractPresentationRecordFromDcqlVpToken(vpToken, opts)) } export const extractPresentationsFromVpToken = ( diff --git a/packages/siop-oid4vp/lib/authorization-response/Payload.ts b/packages/siop-oid4vp/lib/authorization-response/Payload.ts index 286c3705..3016f1b9 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Payload.ts @@ -1,3 +1,5 @@ +import { DcqlPresentationRecord } from 'dcql' + import { AuthorizationRequest } from '../authorization-request' import { IDToken } from '../id-token' import { RequestObject } from '../request-object' @@ -29,7 +31,7 @@ export const createResponsePayload = async ( // vp tokens if (responseOpts.dcqlQuery) { - responsePayload.vp_token = JSON.stringify(responseOpts.dcqlQuery.credentialQueryIdToPresentation) + responsePayload.vp_token = DcqlPresentationRecord.encode(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord) } else { await putPresentationSubmissionInLocation(authorizationRequest, responsePayload, responseOpts, idTokenPayload) } diff --git a/packages/siop-oid4vp/lib/authorization-response/types.ts b/packages/siop-oid4vp/lib/authorization-response/types.ts index 944e0296..aa684320 100644 --- a/packages/siop-oid4vp/lib/authorization-response/types.ts +++ b/packages/siop-oid4vp/lib/authorization-response/types.ts @@ -62,11 +62,7 @@ export interface PresentationExchangeResponseOpts { } export interface DcqlQueryResponseOpts { - credentialQueryIdToPresentation: Record | string> -} - -export interface PresentationExchangeRequestOpts { - presentationVerificationCallback?: PresentationVerificationCallback + encodedPresentationRecord: Record | string> } export interface PresentationDefinitionPayloadOpts { diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index f4665713..6f3b54f8 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -2342,7 +2342,7 @@ export const AuthorizationResponseOptsSchemaObj = { "DcqlQueryResponseOpts": { "type": "object", "properties": { - "credentialQueryIdToPresentation": { + "encodedPresentationRecord": { "type": "object", "additionalProperties": { "anyOf": [ @@ -2358,7 +2358,7 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ - "credentialQueryIdToPresentation" + "encodedPresentationRecord" ], "additionalProperties": false } diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 3933216e..abb6bcab 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -167,7 +167,7 @@ export interface IDTokenPayload extends JWTPayload { } } -export type DcqlQueryVpToken = string +export type EcodedDcqlQueryVpToken = string export interface AuthorizationResponsePayload { access_token?: string @@ -181,7 +181,7 @@ export interface AuthorizationResponsePayload { | W3CVerifiablePresentation | CompactSdJwtVc | MdocOid4vpMdocVpToken - | DcqlQueryVpToken + | EcodedDcqlQueryVpToken presentation_submission?: PresentationSubmission verifiedData?: IPresentation | AdditionalClaims // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index ad8ea863..213f2c2d 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "link:../../../dcql/dcql", + "dcql": "^0.2.7", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.129", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b16db23d..c5b50416 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: link:../../../dcql/dcql - version: link:../../../dcql/dcql + specifier: ^0.2.7 + version: 0.2.7(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -4079,6 +4079,9 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dcql@0.2.7: + resolution: {integrity: sha512-Aap1BFjFDHYmtwDWk4v/lhpfZXfnNeQ4WDSIR4pU48kb5FQjnwXkI0csr2Vij8F1nxn0SHWdDiq5iIasJeUDBQ==} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -8506,6 +8509,14 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + valibot@0.37.0: + resolution: {integrity: sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + valibot@0.42.1: resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} peerDependencies: @@ -14455,6 +14466,12 @@ snapshots: dayjs@1.11.13: {} + dcql@0.2.7(typescript@5.4.5): + dependencies: + valibot: 0.37.0(typescript@5.4.5) + transitivePeerDependencies: + - typescript + debug@2.6.9: dependencies: ms: 2.0.0 @@ -20076,6 +20093,10 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + valibot@0.37.0(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + valibot@0.42.1(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 From 6ad4d89e6ad97b4d4d1155722e71477e36decc59 Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Thu, 21 Nov 2024 14:12:14 +0100 Subject: [PATCH 07/60] feat: add things --- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 213f2c2d..007e4490 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.7", + "dcql": "^0.2.8", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.129", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5b50416..258681de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.7 - version: 0.2.7(typescript@5.4.5) + specifier: ^0.2.8 + version: 0.2.8(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -4079,8 +4079,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.7: - resolution: {integrity: sha512-Aap1BFjFDHYmtwDWk4v/lhpfZXfnNeQ4WDSIR4pU48kb5FQjnwXkI0csr2Vij8F1nxn0SHWdDiq5iIasJeUDBQ==} + dcql@0.2.8: + resolution: {integrity: sha512-/2TbRz3Itj/as4JnmzkupNxq6slN/w07EEx9iAwb/LRI8M8ajhnSN7YQ8rFopImuZAZkPYzOs4zga7zH6xf8eg==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -14466,7 +14466,7 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.7(typescript@5.4.5): + dcql@0.2.8(typescript@5.4.5): dependencies: valibot: 0.37.0(typescript@5.4.5) transitivePeerDependencies: From 6d94367ad7c64a6ca4e170b54cd83e7e490b8d6b Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Thu, 21 Nov 2024 17:52:24 +0100 Subject: [PATCH 08/60] feat: update dcql lib --- package.json | 3 +- .../AuthorizationResponse.ts | 4 +- .../lib/authorization-response/Dcql.ts | 10 +++- .../lib/authorization-response/OpenID4VP.ts | 4 +- .../lib/authorization-response/index.ts | 1 + packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 49 ++++++++----------- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index ac994988..7d119b6c 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,5 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ], - "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" + ] } diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 8e64938f..0e2c8112 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -6,7 +6,7 @@ import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-requ import { IDToken } from '../id-token' import { AuthorizationResponsePayload, ResponseType, SIOPErrors, VerifiedAuthorizationRequest, VerifiedAuthorizationResponse } from '../types' -import { assertValidDcqlPresentationRecrod } from './Dcql' +import { assertValidDcqlPresentationRecord } from './Dcql' import { assertValidVerifiablePresentations, extractNonceFromWrappedVerifiablePresentation, @@ -148,7 +148,7 @@ export class AuthorizationResponse { if (!dcqlQuery) { throw new Error('vp_token is present, but no presentation definitions or dcql query provided') } - assertValidDcqlPresentationRecrod(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord, dcqlQuery, { + assertValidDcqlPresentationRecord(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord, dcqlQuery, { hasher: verifyOpts.hasher, }) } diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index b2488e2e..86bd5e83 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -1,5 +1,6 @@ import { Hasher } from '@sphereon/ssi-types' import { DcqlMdocRepresentation, DcqlPresentationRecord, DcqlQuery, DcqlSdJwtVcRepresentation } from 'dcql' +import { DcqlPresentationQueryResult } from 'dcql' import { extractDataFromPath } from '../helpers' import { AuthorizationRequestPayload, SIOPErrors } from '../types' @@ -37,7 +38,7 @@ export const findValidDcqlQuery = async (authorizationRequestPayload: Authorizat return DcqlQuery.parse(JSON.parse(dcqlQuery[0])) } -export const assertValidDcqlPresentationRecrod = async (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { +export const getDcqlPresentationResult = (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { const wrappedPresentations = Object.values(extractPresentationRecordFromDcqlVpToken(record, opts)) const credentials = wrappedPresentations.map((p) => { if (p.format === 'mso_mdoc') { @@ -49,5 +50,10 @@ export const assertValidDcqlPresentationRecrod = async (record: DcqlPresentation } }) - DcqlPresentationRecord.validate(credentials, { dcqlQuery }) + return DcqlPresentationQueryResult.query(credentials, { dcqlQuery }) +} + +export const assertValidDcqlPresentationRecord = async (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { + const result = getDcqlPresentationResult(record, dcqlQuery, opts) + return DcqlPresentationQueryResult.validate(result) } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index d1a4e72e..7de528a8 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -26,7 +26,7 @@ import { } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' -import { assertValidDcqlPresentationRecrod } from './Dcql' +import { assertValidDcqlPresentationRecord } from './Dcql' import { PresentationExchange } from './PresentationExchange' import { AuthorizationResponseOpts, @@ -98,7 +98,7 @@ export const verifyPresentations = async ( ), ) - assertValidDcqlPresentationRecrod(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) + assertValidDcqlPresentationRecord(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) if (verifiedPresentations.some((verified) => !verified)) { const message = verifiedPresentations diff --git a/packages/siop-oid4vp/lib/authorization-response/index.ts b/packages/siop-oid4vp/lib/authorization-response/index.ts index c8ae3c97..5fff5253 100644 --- a/packages/siop-oid4vp/lib/authorization-response/index.ts +++ b/packages/siop-oid4vp/lib/authorization-response/index.ts @@ -3,3 +3,4 @@ export * from './types' export * from './Payload' export * from './ResponseRegistration' export * from './OpenID4VP' +export * from './Dcql' diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 007e4490..ba6634e1 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.8", + "dcql": "^0.2.11", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.129", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 258681de..d62e60f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.8 - version: 0.2.8(typescript@5.4.5) + specifier: ^0.2.11 + version: 0.2.11(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -1867,7 +1867,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/cli@0.7.3': resolution: {integrity: sha512-uMGHbAhApqXR2sd1KPhgvpbOhBBnspad8msEqHleT2PHXwKIwTUDzBGO9+jdOAWwCx2MJfw3+asYjzoD3DN9Bg==} @@ -2547,7 +2547,6 @@ packages: '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': resolution: {integrity: sha512-uAZZExVy+ug9JLircejWa5eLtAZ7bnBP6xb7DO2+86LRsHNLh2k2jMWJYxp+iWtGHTsh6RYsZl14ScQLvjiQ/A==} - bundledDependencies: [] '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -3052,6 +3051,7 @@ packages: '@xmldom/xmldom@0.7.13': resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} engines: {node: '>=10.0.0'} + deprecated: this version is no longer supported, please update to at least 0.8.* '@xmldom/xmldom@0.8.10': resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} @@ -3477,6 +3477,7 @@ packages: boolean@3.2.0: resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. bplist-creator@0.1.0: resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} @@ -4079,8 +4080,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.8: - resolution: {integrity: sha512-/2TbRz3Itj/as4JnmzkupNxq6slN/w07EEx9iAwb/LRI8M8ajhnSN7YQ8rFopImuZAZkPYzOs4zga7zH6xf8eg==} + dcql@0.2.11: + resolution: {integrity: sha512-hR8MuSx49b7JPoZztcFMSKEHc6iEE4l/Zs6aUsvMCWVa3qFWpuJRiJEp5Rh2+UkCAhsce94fbDpMdBTcS9zn7g==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -4238,10 +4239,6 @@ packages: did-context@3.1.1: resolution: {integrity: sha512-iFpszgSxc7d1kNBJWC+PAzNTpe5LPalzsIunTMIpbG3O37Q7Zi7u4iIaedaM7UhziBhT+Agr9DyvAiXSUyfepQ==} - did-jwt-vc@3.1.3: - resolution: {integrity: sha512-qB1FiQ0sT/FUR5+mQ//P5lS0Gllrtes2OxC3WVMOt8ND0LolF92ohozv50ukyOvB2zBzgfm5durcIPqQcoI+LA==} - engines: {node: '>=14'} - did-jwt-vc@3.2.15: resolution: {integrity: sha512-M/WPiL34CQUiN4bvWnZ0OFHJ3usPtstfQfbNbHAWHvwjeCGi7nAdv62VXHgy2xIhJMc790hH7PsMN3i6SCGEyg==} engines: {node: '>=18'} @@ -4518,6 +4515,7 @@ packages: eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true esm@3.2.25: @@ -10795,7 +10793,7 @@ snapshots: '@expo/bunyan': 4.0.0 '@expo/metro-config': 0.7.1 '@expo/osascript': 2.0.33 - '@expo/spawn-async': 1.5.0 + '@expo/spawn-async': 1.7.2 body-parser: 1.20.3 chalk: 4.1.2 connect: 3.7.0 @@ -10871,7 +10869,7 @@ snapshots: '@expo/osascript@2.0.33': dependencies: - '@expo/spawn-async': 1.5.0 + '@expo/spawn-async': 1.7.2 exec-async: 2.2.0 '@expo/osascript@2.1.3': @@ -10882,7 +10880,7 @@ snapshots: '@expo/package-manager@1.0.3': dependencies: '@expo/json-file': 8.3.3 - '@expo/spawn-async': 1.5.0 + '@expo/spawn-async': 1.7.2 ansi-regex: 5.0.1 chalk: 4.1.2 find-up: 5.0.0 @@ -13199,7 +13197,7 @@ snapshots: cross-fetch: 3.1.8(encoding@0.1.13) debug: 4.3.7 did-jwt: 6.11.6 - did-jwt-vc: 3.1.3 + did-jwt-vc: 3.2.15 did-resolver: 4.1.0 elliptic: 6.5.7 multiformats: 9.7.1 @@ -14466,7 +14464,7 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.8(typescript@5.4.5): + dcql@0.2.11(typescript@5.4.5): dependencies: valibot: 0.37.0(typescript@5.4.5) transitivePeerDependencies: @@ -14600,11 +14598,6 @@ snapshots: did-context@3.1.1: {} - did-jwt-vc@3.1.3: - dependencies: - did-jwt: 6.11.6 - did-resolver: 4.1.0 - did-jwt-vc@3.2.15: dependencies: did-jwt: 7.4.7 @@ -15125,9 +15118,9 @@ snapshots: execa@5.0.0: dependencies: cross-spawn: 7.0.3 - get-stream: 6.0.0 + get-stream: 6.0.1 human-signals: 2.1.0 - is-stream: 2.0.0 + is-stream: 2.0.1 merge-stream: 2.0.0 npm-run-path: 4.0.1 onetime: 5.1.2 @@ -16468,7 +16461,7 @@ snapshots: jest-diff@29.7.0: dependencies: - chalk: 4.1.0 + chalk: 4.1.2 diff-sequences: 29.6.3 jest-get-type: 29.6.3 pretty-format: 29.7.0 @@ -17253,7 +17246,7 @@ snapshots: log-symbols@4.1.0: dependencies: - chalk: 4.1.0 + chalk: 4.1.2 is-unicode-supported: 0.1.0 logkitty@0.7.1: @@ -17885,7 +17878,7 @@ snapshots: array-differ: 3.0.0 array-union: 2.1.0 arrify: 2.0.1 - minimatch: 3.0.5 + minimatch: 3.1.2 mute-stream@0.0.8: {} @@ -18116,7 +18109,7 @@ snapshots: '@yarnpkg/parsers': 3.0.0-rc.46 '@zkochan/js-yaml': 0.0.7 axios: 1.7.7(debug@4.3.7) - chalk: 4.1.0 + chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 cliui: 8.0.1 @@ -18299,9 +18292,9 @@ snapshots: ora@5.3.0: dependencies: bl: 4.1.0 - chalk: 4.1.0 + chalk: 4.1.2 cli-cursor: 3.1.0 - cli-spinners: 2.6.1 + cli-spinners: 2.9.2 is-interactive: 1.0.0 log-symbols: 4.1.0 strip-ansi: 6.0.1 From 413ecb9af2fa4010ef177272d320045f6148747f Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Fri, 22 Nov 2024 19:58:53 +0100 Subject: [PATCH 09/60] fix: feedback --- package.json | 3 +- .../AuthorizationRequest.ts | 2 +- .../AuthorizationResponse.ts | 56 +++++++++---------- .../lib/authorization-response/Dcql.ts | 36 ++++++------ .../lib/authorization-response/OpenID4VP.ts | 33 ++++++----- .../lib/authorization-response/Payload.ts | 4 +- .../lib/authorization-response/types.ts | 2 +- .../AuthorizationResponseOpts.schema.ts | 4 +- packages/siop-oid4vp/lib/types/Errors.ts | 2 +- packages/siop-oid4vp/lib/types/SIOP.types.ts | 6 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 13 +++-- 12 files changed, 84 insertions(+), 79 deletions(-) diff --git a/package.json b/package.json index 7d119b6c..ac994988 100644 --- a/package.json +++ b/package.json @@ -63,5 +63,6 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ] + ], + "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" } diff --git a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts index aeb4b15b..c3bfd6ed 100644 --- a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts +++ b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts @@ -290,7 +290,7 @@ export class AuthorizationRequest { return await PresentationExchange.findValidPresentationDefinitions(await this.mergedPayloads(), version) } - public async getDcqlQuery(): Promise { + public async getDcqlQuery(): Promise { return await findValidDcqlQuery(await this.mergedPayloads()) } } diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 0e2c8112..26fa302c 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -1,12 +1,12 @@ import { CredentialMapper, Hasher, WrappedVerifiablePresentation } from '@sphereon/ssi-types' -import { DcqlPresentationRecord } from 'dcql' +import { DcqlPresentation } from 'dcql' import { AuthorizationRequest, VerifyAuthorizationRequestOpts } from '../authorization-request' import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-request/Opts' import { IDToken } from '../id-token' import { AuthorizationResponsePayload, ResponseType, SIOPErrors, VerifiedAuthorizationRequest, VerifiedAuthorizationResponse } from '../types' -import { assertValidDcqlPresentationRecord } from './Dcql' +import { assertValidDcqlPresentation } from './Dcql' import { assertValidVerifiablePresentations, extractNonceFromWrappedVerifiablePresentation, @@ -126,32 +126,32 @@ export class AuthorizationResponse { authorizationRequest, }) - if (hasVpToken) { - if (responseOpts.presentationExchange) { - const wrappedPresentations = response.payload.vp_token - ? await extractPresentationsFromVpToken(response.payload.vp_token, { - hasher: verifyOpts.hasher, - }) - : [] - - await assertValidVerifiablePresentations({ - presentationDefinitions, - presentations: wrappedPresentations, - verificationCallback: verifyOpts.verification.presentationVerificationCallback, - opts: { - ...responseOpts.presentationExchange, + if (!hasVpToken) return response + + if (responseOpts.presentationExchange) { + const wrappedPresentations = response.payload.vp_token + ? await extractPresentationsFromVpToken(response.payload.vp_token, { hasher: verifyOpts.hasher, - }, - }) - } else { - const dcqlQuery = verifiedAuthorizationRequest.dcqlQuery - if (!dcqlQuery) { - throw new Error('vp_token is present, but no presentation definitions or dcql query provided') - } - assertValidDcqlPresentationRecord(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord, dcqlQuery, { + }) + : [] + + await assertValidVerifiablePresentations({ + presentationDefinitions, + presentations: wrappedPresentations, + verificationCallback: verifyOpts.verification.presentationVerificationCallback, + opts: { + ...responseOpts.presentationExchange, hasher: verifyOpts.hasher, - }) + }, + }) + } else { + const dcqlQuery = verifiedAuthorizationRequest.dcqlQuery + if (!dcqlQuery) { + throw new Error('vp_token is present, but no presentation definitions or dcql query provided') } + assertValidDcqlPresentation(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, dcqlQuery, { + hasher: verifyOpts.hasher, + }) } return response @@ -181,7 +181,7 @@ export class AuthorizationResponse { // Gather all nonces const allNonces = new Set() - if (oid4vp && oid4vp.nonce) allNonces.add(oid4vp.nonce) + if (oid4vp && (oid4vp.dcql.nonce || oid4vp.presentationExchange.nonce)) allNonces.add(oid4vp.dcql.nonce ?? oid4vp.presentationExchange.nonce) if (verifiedIdToken) allNonces.add(verifiedIdToken.payload.nonce) if (merged.nonce) allNonces.add(merged.nonce) @@ -207,8 +207,8 @@ export class AuthorizationResponse { state, correlationId: verifyOpts.correlationId, ...(this.idToken && { idToken: verifiedIdToken }), - ...(oid4vp && 'presentationDefinitions' in oid4vp && { oid4vpSubmission: oid4vp }), - ...(oid4vp && 'dcqlQuery' in oid4vp && { oid4vpSubmissionDcql: oid4vp }), + ...(oid4vp.presentationExchange && { oid4vpSubmission: oid4vp.presentationExchange }), + ...(oid4vp.dcql && { oid4vpSubmissionDcql: oid4vp.dcql }), } } diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index 86bd5e83..71662d91 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -1,11 +1,10 @@ import { Hasher } from '@sphereon/ssi-types' -import { DcqlMdocRepresentation, DcqlPresentationRecord, DcqlQuery, DcqlSdJwtVcRepresentation } from 'dcql' -import { DcqlPresentationQueryResult } from 'dcql' +import { DcqlMdocCredential, DcqlPresentation, DcqlPresentationResult, DcqlQuery, DcqlSdJwtVcCredential } from 'dcql' import { extractDataFromPath } from '../helpers' import { AuthorizationRequestPayload, SIOPErrors } from '../types' -import { extractPresentationRecordFromDcqlVpToken } from './OpenID4VP' +import { extractDcqlPresentationFromDcqlVpToken } from './OpenID4VP' /** * Finds a valid DcqlQuery inside the given AuthenticationRequestPayload @@ -38,22 +37,23 @@ export const findValidDcqlQuery = async (authorizationRequestPayload: Authorizat return DcqlQuery.parse(JSON.parse(dcqlQuery[0])) } -export const getDcqlPresentationResult = (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { - const wrappedPresentations = Object.values(extractPresentationRecordFromDcqlVpToken(record, opts)) - const credentials = wrappedPresentations.map((p) => { - if (p.format === 'mso_mdoc') { - return { docType: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocRepresentation - } else if (p.format === 'vc+sd-jwt') { - return { vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcRepresentation - } else { - throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') - } - }) - - return DcqlPresentationQueryResult.query(credentials, { dcqlQuery }) +export const getDcqlPresentationResult = (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { + const dcqlPresentation = Object.fromEntries( + Object.entries(extractDcqlPresentationFromDcqlVpToken(record, opts)).map(([queryId, p]) => { + if (p.format === 'mso_mdoc') { + return [queryId, { docType: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential] + } else if (p.format === 'vc+sd-jwt') { + return [queryId, { vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] + } else { + throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') + } + }), + ) + + return DcqlPresentationResult.fromDcqlPresentation(dcqlPresentation, { dcqlQuery }) } -export const assertValidDcqlPresentationRecord = async (record: DcqlPresentationRecord | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { +export const assertValidDcqlPresentation = async (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { const result = getDcqlPresentationResult(record, dcqlQuery, opts) - return DcqlPresentationQueryResult.validate(result) + return DcqlPresentationResult.validate(result) } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 7de528a8..3f1c8b30 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -10,7 +10,7 @@ import { W3CVerifiablePresentation, WrappedVerifiablePresentation, } from '@sphereon/ssi-types' -import { DcqlPresentationRecord, DcqlQuery } from 'dcql' +import { DcqlPresentation, DcqlQuery } from 'dcql' import { AuthorizationRequest } from '../authorization-request' import { verifyRevocation } from '../helpers' @@ -26,7 +26,7 @@ import { } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' -import { assertValidDcqlPresentationRecord } from './Dcql' +import { assertValidDcqlPresentation as assertValidDcqlPresentation } from './Dcql' import { PresentationExchange } from './PresentationExchange' import { AuthorizationResponseOpts, @@ -72,7 +72,7 @@ export const extractNonceFromWrappedVerifiablePresentation = (wrappedVp: Wrapped export const verifyPresentations = async ( authorizationResponse: AuthorizationResponse, verifyOpts: VerifyAuthorizationResponseOpts, -): Promise => { +): Promise<{ presentationExchange?: VerifiedOpenID4VPSubmission; dcql?: VerifiedOpenID4VPSubmissionDcql }> => { let idPayload: IDTokenPayload | undefined if (authorizationResponse.idToken) { idPayload = await authorizationResponse.idToken.payload() @@ -87,10 +87,13 @@ export const verifyPresentations = async ( let presentationSubmission: PresentationSubmission | undefined + let dcqlPresentation: { [credentialQueryId: string]: WrappedVerifiablePresentation } | undefined + let dcqlQuery = verifyOpts.dcqlQuery ?? authorizationResponse?.authorizationRequest?.payload.dcql_query if (dcqlQuery) { dcqlQuery = DcqlQuery.parse(dcqlQuery) - wrappedPresentations = extractPresentationsFromDcqlVpToken(authorizationResponse.payload.vp_token as string, { hasher: verifyOpts.hasher }) + dcqlPresentation = extractDcqlPresentationFromDcqlVpToken(authorizationResponse.payload.vp_token as string, { hasher: verifyOpts.hasher }) + wrappedPresentations = Object.values(dcqlPresentation) const verifiedPresentations = await Promise.all( wrappedPresentations.map((presentation) => @@ -98,7 +101,7 @@ export const verifyPresentations = async ( ), ) - assertValidDcqlPresentationRecord(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) + assertValidDcqlPresentation(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) if (verifiedPresentations.some((verified) => !verified)) { const message = verifiedPresentations @@ -154,31 +157,31 @@ export const verifyPresentations = async ( } } if (presentationDefinitions) { - return { nonce, presentations: wrappedPresentations, presentationDefinitions, submissionData: presentationSubmission } + return { presentationExchange: { nonce, presentations: wrappedPresentations, presentationDefinitions, submissionData: presentationSubmission } } } else { - return { nonce, presentations: wrappedPresentations, dcqlQuery } + return { dcql: { nonce, presentation: dcqlPresentation, dcqlQuery } } } } -export const extractPresentationRecordFromDcqlVpToken = ( - vpToken: DcqlPresentationRecord.Input | string, +export const extractDcqlPresentationFromDcqlVpToken = ( + vpToken: DcqlPresentation.Input | string, opts?: { hasher?: Hasher }, -): Record => { - const presentationRecord = Object.fromEntries( - Object.entries(DcqlPresentationRecord.parse(vpToken)).map(([credentialQueryId, vp]) => [ +): { [credentialQueryId: string]: WrappedVerifiablePresentation } => { + const dcqlPresentation = Object.fromEntries( + Object.entries(DcqlPresentation.parse(vpToken)).map(([credentialQueryId, vp]) => [ credentialQueryId, CredentialMapper.toWrappedVerifiablePresentation(vp as W3CVerifiablePresentation | CompactSdJwtVc | string, { hasher: opts.hasher }), ]), ) - return presentationRecord + return dcqlPresentation } export const extractPresentationsFromDcqlVpToken = ( - vpToken: DcqlPresentationRecord.Input | string, + vpToken: DcqlPresentation.Input | string, opts?: { hasher?: Hasher }, ): WrappedVerifiablePresentation[] => { - return Object.values(extractPresentationRecordFromDcqlVpToken(vpToken, opts)) + return Object.values(extractDcqlPresentationFromDcqlVpToken(vpToken, opts)) } export const extractPresentationsFromVpToken = ( diff --git a/packages/siop-oid4vp/lib/authorization-response/Payload.ts b/packages/siop-oid4vp/lib/authorization-response/Payload.ts index 3016f1b9..a2bc60b9 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Payload.ts @@ -1,4 +1,4 @@ -import { DcqlPresentationRecord } from 'dcql' +import { DcqlPresentation } from 'dcql' import { AuthorizationRequest } from '../authorization-request' import { IDToken } from '../id-token' @@ -31,7 +31,7 @@ export const createResponsePayload = async ( // vp tokens if (responseOpts.dcqlQuery) { - responsePayload.vp_token = DcqlPresentationRecord.encode(responseOpts.dcqlQuery.encodedPresentationRecord as DcqlPresentationRecord) + responsePayload.vp_token = DcqlPresentation.encode(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation) } else { await putPresentationSubmissionInLocation(authorizationRequest, responsePayload, responseOpts, idTokenPayload) } diff --git a/packages/siop-oid4vp/lib/authorization-response/types.ts b/packages/siop-oid4vp/lib/authorization-response/types.ts index aa684320..5f8f2b6f 100644 --- a/packages/siop-oid4vp/lib/authorization-response/types.ts +++ b/packages/siop-oid4vp/lib/authorization-response/types.ts @@ -62,7 +62,7 @@ export interface PresentationExchangeResponseOpts { } export interface DcqlQueryResponseOpts { - encodedPresentationRecord: Record | string> + dcqlPresentation: Record | string> } export interface PresentationDefinitionPayloadOpts { diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index 6f3b54f8..1478d7b7 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -2342,7 +2342,7 @@ export const AuthorizationResponseOptsSchemaObj = { "DcqlQueryResponseOpts": { "type": "object", "properties": { - "encodedPresentationRecord": { + "dcqlPresentation": { "type": "object", "additionalProperties": { "anyOf": [ @@ -2358,7 +2358,7 @@ export const AuthorizationResponseOptsSchemaObj = { } }, "required": [ - "encodedPresentationRecord" + "dcqlPresentation" ], "additionalProperties": false } diff --git a/packages/siop-oid4vp/lib/types/Errors.ts b/packages/siop-oid4vp/lib/types/Errors.ts index 780d8c17..fa08b9d8 100644 --- a/packages/siop-oid4vp/lib/types/Errors.ts +++ b/packages/siop-oid4vp/lib/types/Errors.ts @@ -38,7 +38,7 @@ enum SIOPErrors { REFERENCE_URI_NO_PAYLOAD = 'referenceUri specified, but object to host there is not present', NO_SELF_ISSUED_ISS = 'The Response Token Issuer Claim (iss) MUST start with https://self-isued.me/v2', REGISTRATION_NOT_SET = 'Registration metadata not set.', - REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE = "Request claims can't multiple of 'presentation_definition' and 'presentation_definition_uri' 'dcql_query", + REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE = "Request claims can't have multiple of 'presentation_definition', 'presentation_definition_uri' and 'dcql_query", REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID = 'Presentation definition in the request claims is not valid', REQUEST_OBJECT_TYPE_NOT_SET = 'Request object type is not set.', RESPONSE_OPTS_PRESENTATIONS_SUBMISSION_IS_NOT_VALID = 'presentation_submission object inside the response opts vp should be valid', diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index abb6bcab..e0b78ff8 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -167,7 +167,7 @@ export interface IDTokenPayload extends JWTPayload { } } -export type EcodedDcqlQueryVpToken = string +export type EncodedDcqlQueryVpToken = string export interface AuthorizationResponsePayload { access_token?: string @@ -181,7 +181,7 @@ export interface AuthorizationResponsePayload { | W3CVerifiablePresentation | CompactSdJwtVc | MdocOid4vpMdocVpToken - | EcodedDcqlQueryVpToken + | EncodedDcqlQueryVpToken presentation_submission?: PresentationSubmission verifiedData?: IPresentation | AdditionalClaims // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -518,7 +518,7 @@ export interface VerifiedIDToken { export interface VerifiedOpenID4VPSubmissionDcql { dcqlQuery: DcqlQuery - presentations: WrappedVerifiablePresentation[] + presentation: { [credentialQueryId: string]: WrappedVerifiablePresentation } nonce?: string } diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index ba6634e1..dd294260 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.11", + "dcql": "^0.2.12", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.129", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d62e60f5..9b647e54 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.11 - version: 0.2.11(typescript@5.4.5) + specifier: ^0.2.12 + version: 0.2.12(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -1867,7 +1867,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {node: '>=0.10.0'} + engines: {'0': node >=0.10.0} '@expo/cli@0.7.3': resolution: {integrity: sha512-uMGHbAhApqXR2sd1KPhgvpbOhBBnspad8msEqHleT2PHXwKIwTUDzBGO9+jdOAWwCx2MJfw3+asYjzoD3DN9Bg==} @@ -2547,6 +2547,7 @@ packages: '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': resolution: {integrity: sha512-uAZZExVy+ug9JLircejWa5eLtAZ7bnBP6xb7DO2+86LRsHNLh2k2jMWJYxp+iWtGHTsh6RYsZl14ScQLvjiQ/A==} + bundledDependencies: [] '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -4080,8 +4081,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.11: - resolution: {integrity: sha512-hR8MuSx49b7JPoZztcFMSKEHc6iEE4l/Zs6aUsvMCWVa3qFWpuJRiJEp5Rh2+UkCAhsce94fbDpMdBTcS9zn7g==} + dcql@0.2.12: + resolution: {integrity: sha512-Ag2HTeMio8Gz8/K2T+VrT9wx+nxBst4goOeYbD/UXfiRnbH1MuPW1JW8zlmHmWFfzxl7KikaiQtr1ipLwNCYNA==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -14464,7 +14465,7 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.11(typescript@5.4.5): + dcql@0.2.12(typescript@5.4.5): dependencies: valibot: 0.37.0(typescript@5.4.5) transitivePeerDependencies: From 9ff62bd5127a69f33a158fe8f0be21ca9820879a Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Sat, 23 Nov 2024 09:59:56 +0100 Subject: [PATCH 10/60] fix: update --- .../AuthorizationResponse.ts | 10 +++++----- .../siop-oid4vp/lib/authorization-response/Dcql.ts | 9 ++++++--- .../lib/authorization-response/OpenID4VP.ts | 14 +++++++------- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 12 ++++++------ 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 26fa302c..c1c71212 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -6,7 +6,7 @@ import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-requ import { IDToken } from '../id-token' import { AuthorizationResponsePayload, ResponseType, SIOPErrors, VerifiedAuthorizationRequest, VerifiedAuthorizationResponse } from '../types' -import { assertValidDcqlPresentation } from './Dcql' +import { assertValidDcqlPresentationResult } from './Dcql' import { assertValidVerifiablePresentations, extractNonceFromWrappedVerifiablePresentation, @@ -149,7 +149,7 @@ export class AuthorizationResponse { if (!dcqlQuery) { throw new Error('vp_token is present, but no presentation definitions or dcql query provided') } - assertValidDcqlPresentation(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, dcqlQuery, { + assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, dcqlQuery, { hasher: verifyOpts.hasher, }) } @@ -169,19 +169,19 @@ export class AuthorizationResponse { const verifiedIdToken = await this.idToken?.verify(verifyOpts) if (this.payload.vp_token && !verifyOpts.presentationDefinitions && !verifyOpts.dcqlQuery) { - throw Promise.reject(Error('vp_token is present, but no presentation definitions or dcql query provided')) + throw new Error('vp_token is present, but no presentation definitions or dcql query provided') } const emptyPresentationDefinitions = Array.isArray(verifyOpts.presentationDefinitions) && verifyOpts.presentationDefinitions.length === 0 if (!this.payload.vp_token && ((verifyOpts.presentationDefinitions && !emptyPresentationDefinitions) || verifyOpts.dcqlQuery)) { - throw Promise.reject(Error('Presentation definitions or dcql query provided, but no vp_token present')) + throw new Error('Presentation definitions or dcql query provided, but no vp_token present') } const oid4vp = this.payload.vp_token ? await verifyPresentations(this, verifyOpts) : undefined // Gather all nonces const allNonces = new Set() - if (oid4vp && (oid4vp.dcql.nonce || oid4vp.presentationExchange.nonce)) allNonces.add(oid4vp.dcql.nonce ?? oid4vp.presentationExchange.nonce) + if (oid4vp && (oid4vp.dcql?.nonce || oid4vp.presentationExchange?.nonce)) allNonces.add(oid4vp.dcql?.nonce ?? oid4vp.presentationExchange?.nonce) if (verifiedIdToken) allNonces.add(verifiedIdToken.payload.nonce) if (merged.nonce) allNonces.add(merged.nonce) diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index 71662d91..77ab1da5 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -41,9 +41,12 @@ export const getDcqlPresentationResult = (record: DcqlPresentation | string, dcq const dcqlPresentation = Object.fromEntries( Object.entries(extractDcqlPresentationFromDcqlVpToken(record, opts)).map(([queryId, p]) => { if (p.format === 'mso_mdoc') { - return [queryId, { docType: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential] + return [ + queryId, + { credentialFormat: 'mso_mdoc', doctype: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential, + ] } else if (p.format === 'vc+sd-jwt') { - return [queryId, { vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] + return [queryId, { credentialFormat: 'vc+sd-jwt', vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] } else { throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') } @@ -53,7 +56,7 @@ export const getDcqlPresentationResult = (record: DcqlPresentation | string, dcq return DcqlPresentationResult.fromDcqlPresentation(dcqlPresentation, { dcqlQuery }) } -export const assertValidDcqlPresentation = async (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { +export const assertValidDcqlPresentationResult = async (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { const result = getDcqlPresentationResult(record, dcqlQuery, opts) return DcqlPresentationResult.validate(result) } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 9dc1aeef..d1177ef4 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -26,7 +26,7 @@ import { } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' -import { assertValidDcqlPresentation as assertValidDcqlPresentation } from './Dcql' +import { assertValidDcqlPresentationResult } from './Dcql' import { PresentationExchange } from './PresentationExchange' import { AuthorizationResponseOpts, @@ -101,7 +101,7 @@ export const verifyPresentations = async ( ), ) - assertValidDcqlPresentation(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) + assertValidDcqlPresentationResult(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) if (verifiedPresentations.some((verified) => !verified)) { const message = verifiedPresentations @@ -337,14 +337,14 @@ export const assertValidVerifiablePresentations = async (args: { if (!presentations || (Array.isArray(presentations) && presentations.length === 0)) { return Promise.reject(Error('missing presentation(s)')) } - + // Handle mdocs, keep them out of pex - let presentationsArray = (Array.isArray(presentations) ? presentations : [presentations]) - if (presentationsArray.every(p => p.format === 'mso_mdoc')) { + let presentationsArray = Array.isArray(presentations) ? presentations : [presentations] + if (presentationsArray.every((p) => p.format === 'mso_mdoc')) { return - } + } presentationsArray = presentationsArray.filter((p) => p.format !== 'mso_mdoc') - + if ( (!args.presentationDefinitions || args.presentationDefinitions.filter((a) => a.definition).length === 0) && (!presentationsArray || (Array.isArray(presentationsArray) && presentationsArray.filter((vp) => vp.presentation).length === 0)) diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 52e37a7f..937ce385 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.12", + "dcql": "^0.2.13", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.279", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e89464f..f4e47bc6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.12 - version: 0.2.12(typescript@5.4.5) + specifier: ^0.2.13 + version: 0.2.13(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -1867,7 +1867,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/cli@0.7.3': resolution: {integrity: sha512-uMGHbAhApqXR2sd1KPhgvpbOhBBnspad8msEqHleT2PHXwKIwTUDzBGO9+jdOAWwCx2MJfw3+asYjzoD3DN9Bg==} @@ -4015,8 +4015,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.12: - resolution: {integrity: sha512-Ag2HTeMio8Gz8/K2T+VrT9wx+nxBst4goOeYbD/UXfiRnbH1MuPW1JW8zlmHmWFfzxl7KikaiQtr1ipLwNCYNA==} + dcql@0.2.13: + resolution: {integrity: sha512-XfePsSz9ULj9HH3VFNguzK/xlFnliKDX2iUDb1tIrn97S+TfftcFo+jipw16m9jPlWLhhBx48QniF0D8KotIWA==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -13835,7 +13835,7 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.12(typescript@5.4.5): + dcql@0.2.13(typescript@5.4.5): dependencies: valibot: 0.37.0(typescript@5.4.5) transitivePeerDependencies: From c654a7bce3dd659d48d7cf3fdfa5d6f23b23a3f4 Mon Sep 17 00:00:00 2001 From: Timo Glastra Date: Sun, 24 Nov 2024 14:07:27 +0100 Subject: [PATCH 11/60] fix: check if oid4vp defined Signed-off-by: Timo Glastra --- .../lib/authorization-response/AuthorizationResponse.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index c1c71212..09d91a6c 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -207,8 +207,8 @@ export class AuthorizationResponse { state, correlationId: verifyOpts.correlationId, ...(this.idToken && { idToken: verifiedIdToken }), - ...(oid4vp.presentationExchange && { oid4vpSubmission: oid4vp.presentationExchange }), - ...(oid4vp.dcql && { oid4vpSubmissionDcql: oid4vp.dcql }), + ...(oid4vp?.presentationExchange && { oid4vpSubmission: oid4vp.presentationExchange }), + ...(oid4vp?.dcql && { oid4vpSubmissionDcql: oid4vp.dcql }), } } From 2f91ee2854a63c9633f7259d50e6c5b2b5fc085e Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 25 Nov 2024 13:35:19 +0100 Subject: [PATCH 12/60] chore: Resolve the OID Federation metadata oid4vp --- .../lib/authorization-request/URI.ts | 34 ++++++-- packages/siop-oid4vp/lib/op/OP.ts | 4 +- packages/siop-oid4vp/lib/op/OPBuilder.ts | 6 ++ packages/siop-oid4vp/package.json | 5 ++ pnpm-lock.yaml | 85 ++++++++++++++++++- 5 files changed, 123 insertions(+), 11 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/URI.ts b/packages/siop-oid4vp/lib/authorization-request/URI.ts index 7aa04815..f1dceb2f 100644 --- a/packages/siop-oid4vp/lib/authorization-request/URI.ts +++ b/packages/siop-oid4vp/lib/authorization-request/URI.ts @@ -1,4 +1,5 @@ import { parseJWT } from '@sphereon/oid4vc-common' +import { FederationClient, TrustChainResolveResponse } from '@sphereon/openid-federation-client' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { decodeUriAsJson, encodeJsonAsURI, fetchByReferenceOrUseByValue } from '../helpers' @@ -126,7 +127,6 @@ export class URI implements AuthorizationRequestURI { ...authorizationRequest.options.requestObject, version: authorizationRequest.options.version, uriScheme: authorizationRequest.options.uriScheme, - }, authorizationRequest.payload, authorizationRequest.requestObject, @@ -194,7 +194,8 @@ export class URI implements AuthorizationRequestURI { } } else { try { - scheme = (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' + scheme = + (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' } catch (error: unknown) { scheme = 'openid4vp://' } @@ -235,16 +236,35 @@ export class URI implements AuthorizationRequestURI { return { scheme, authorizationRequestPayload } } - public static async parseAndResolve(uri: string) { + public static async parseAndResolve(uri: string, trustChain?: Array) { if (!uri) { throw Error(SIOPErrors.BAD_PARAMS) } const { authorizationRequestPayload, scheme } = this.parse(uri) + const requestObjectJwt = await fetchByReferenceOrUseByValue(authorizationRequestPayload.request_uri, authorizationRequestPayload.request, true) - const registrationMetadata: RPRegistrationMetadataPayload = await fetchByReferenceOrUseByValue( - authorizationRequestPayload['client_metadata_uri'] ?? authorizationRequestPayload['registration_uri'], - authorizationRequestPayload['client_metadata'] ?? authorizationRequestPayload['registration'], - ) + let registrationMetadata: RPRegistrationMetadataPayload + if (trustChain !== undefined && trustChain !== null) { + const fedClient = new FederationClient(null, null) + const resolvedTrustChain: TrustChainResolveResponse = await fedClient.resolveTrustChain( + authorizationRequestPayload['client_metadata_uri'], + trustChain, + ) + if (resolvedTrustChain !== null && resolvedTrustChain !== undefined) { + const clientMetadata = resolvedTrustChain.trustChain.asJsReadonlyArrayView()[1] + const subordinateStatement = JSON.parse(Buffer.from(clientMetadata.split('.')[1]).toString('base64url')) + registrationMetadata = {} + registrationMetadata.federation_entity = subordinateStatement.federationEntity + registrationMetadata.openid_credential_verifier = subordinateStatement.openIdRelyingParty + } else { + throw new Error('Cannot resolve OID Federation metadata') + } + } else { + registrationMetadata = await fetchByReferenceOrUseByValue( + authorizationRequestPayload['client_metadata_uri'] ?? authorizationRequestPayload['registration_uri'], + authorizationRequestPayload['client_metadata'] ?? authorizationRequestPayload['registration'], + ) + } assertValidRPRegistrationMedataPayload(registrationMetadata) return { scheme, authorizationRequestPayload, requestObjectJwt, registrationMetadata } } diff --git a/packages/siop-oid4vp/lib/op/OP.ts b/packages/siop-oid4vp/lib/op/OP.ts index 7fee9a0a..abda723d 100644 --- a/packages/siop-oid4vp/lib/op/OP.ts +++ b/packages/siop-oid4vp/lib/op/OP.ts @@ -39,9 +39,11 @@ import { createResponseOptsFromBuilderOrExistingOpts, createVerifyRequestOptsFro export class OP { private readonly _createResponseOptions: AuthorizationResponseOpts private readonly _verifyRequestOptions: Partial + private readonly _trustChain: Array private readonly _eventEmitter?: EventEmitter private constructor(opts: { builder?: OPBuilder; responseOpts?: AuthorizationResponseOpts; verifyOpts?: VerifyAuthorizationRequestOpts }) { + this._trustChain = opts.builder?.trustChain this._createResponseOptions = { ...createResponseOptsFromBuilderOrExistingOpts(opts) } this._verifyRequestOptions = { ...createVerifyRequestOptsFromBuilderOrExistingOpts(opts) } this._eventEmitter = opts.builder?.eventEmitter @@ -276,7 +278,7 @@ export class OP { * @param encodedUri */ public async parseAuthorizationRequestURI(encodedUri: string): Promise { - const { scheme, requestObjectJwt, authorizationRequestPayload, registrationMetadata } = await URI.parseAndResolve(encodedUri) + const { scheme, requestObjectJwt, authorizationRequestPayload, registrationMetadata } = await URI.parseAndResolve(encodedUri, this._trustChain) return { encodedUri, diff --git a/packages/siop-oid4vp/lib/op/OPBuilder.ts b/packages/siop-oid4vp/lib/op/OPBuilder.ts index 6db8dd54..58d8c0bd 100644 --- a/packages/siop-oid4vp/lib/op/OPBuilder.ts +++ b/packages/siop-oid4vp/lib/op/OPBuilder.ts @@ -17,6 +17,7 @@ export class OPBuilder { createJwtCallback?: CreateJwtCallback verifyJwtCallback?: VerifyJwtCallback presentationSignCallback?: PresentationSignCallback + trustChain?: Array supportedVersions?: SupportedVersion[] eventEmitter?: EventEmitter @@ -94,6 +95,11 @@ export class OPBuilder { return this } + withTrustChain(trustChain: Array): OPBuilder { + this.trustChain = trustChain + return this + } + withEventEmitter(eventEmitter?: EventEmitter): OPBuilder { this.eventEmitter = eventEmitter ?? new EventEmitter() return this diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 15398327..b628e628 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -81,6 +81,11 @@ "tsimp": "^2.0.11", "typescript": "5.4.5" }, + "peerDependencies": { + "@sphereon/openid-federation-client": "^0.1.1-unstable.21e8440", + "@sphereon/openid-federation-common": "^0.1.1-unstable.21e8440", + "@sphereon/openid-federation-open-api": "^0.1.1-unstable.21e8440" + }, "resolutions": { "isomorphic-webcrypto": "npm:@sphereon/isomorphic-webcrypto@^2.4.1-unstable.0", "esline/**/strip-ansi": "6.0.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 68b1155e..f1629032 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -448,6 +448,15 @@ importers: '@sphereon/oid4vc-common': specifier: workspace:* version: link:../common + '@sphereon/openid-federation-client': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) + '@sphereon/openid-federation-common': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) + '@sphereon/openid-federation-open-api': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) '@sphereon/pex': specifier: 5.0.0-unstable.24 version: 5.0.0-unstable.24 @@ -2094,6 +2103,9 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@js-joda/core@3.2.0': + resolution: {integrity: sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==} + '@js-joda/core@5.6.3': resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} @@ -2522,6 +2534,16 @@ packages: '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': resolution: {integrity: sha512-uAZZExVy+ug9JLircejWa5eLtAZ7bnBP6xb7DO2+86LRsHNLh2k2jMWJYxp+iWtGHTsh6RYsZl14ScQLvjiQ/A==} + bundledDependencies: [] + + '@sphereon/openid-federation-client@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-O1CW/t3Zan1wKQxdl6fzDXDrL/t+Ph9UB0rypJA4Pr9u4R+7nB+Z3KC/wphH2Q4NrJFP0sASKn0ER78Gc9onLw==} + + '@sphereon/openid-federation-common@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-mumhjoqeP1qjy3SsT/3AExV+x+SwrO4On+ZrMTFNYjzY7zRKl6rKWkgA0iGbG6z2XR7xW3y1wzDqFxIGS94tXQ==} + + '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-glePGlpbvZI+NhhsfoD44cFbamwIMIQF0xG1k1Ikr9i8XRZFBHz/w/WK9Hfc9dtP63Ry2Ckq8I4KlRZLL5OJ6g==} '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -5665,6 +5687,9 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + jose@5.9.4: + resolution: {integrity: sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==} + js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -8501,6 +8526,18 @@ packages: utf-8-validate: optional: true + ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + x25519-key-agreement-2020-context@1.0.0: resolution: {integrity: sha512-zblYd8oSg6hNAD+fA9X7ek1hJQRircl3jVlEVCaBTNN9Mv9b4G32uJvRZFMQEMmda8iaTtYo9i2dRMdXX8pjpA==} @@ -9940,7 +9977,7 @@ snapshots: '@digitalcredentials/bnid@2.1.2(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1))': dependencies: '@digitalcredentials/base58-universal': 1.0.1 - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)) yargs: 15.4.1 transitivePeerDependencies: - react-native @@ -11022,6 +11059,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@js-joda/core@3.2.0': {} + '@js-joda/core@5.6.3': {} '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': @@ -11764,7 +11803,7 @@ snapshots: webcrypto-shim: 0.1.7 optionalDependencies: expo: 48.0.21(@babel/core@7.25.2)(encoding@0.1.13) - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)) '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': dependencies: @@ -11772,6 +11811,42 @@ snapshots: '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) format-util: 1.0.5 + '@sphereon/openid-federation-client@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + '@js-joda/core': 3.2.0 + abort-controller: 3.0.0 + format-util: 1.0.5 + jose: 5.9.4 + node-fetch: 2.6.12(encoding@0.1.13) + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + + '@sphereon/openid-federation-common@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + abort-controller: 3.0.0 + format-util: 1.0.5 + node-fetch: 2.6.12(encoding@0.1.13) + typescript: 5.5.3 + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + + '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + abort-controller: 3.0.0 + format-util: 1.0.5 + node-fetch: 2.6.12(encoding@0.1.13) + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + '@sphereon/pex-models@2.3.1': {} '@sphereon/pex@5.0.0-unstable.24': @@ -16069,6 +16144,8 @@ snapshots: jose@4.15.9: {} + jose@5.9.4: {} + js-base64@3.7.7: {} js-binary-schema-parser@2.0.3: {} @@ -17960,7 +18037,7 @@ snapshots: react-native: 0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1) optional: true - react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1)): + react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.25.2)(encoding@0.1.13)(react@18.3.1)): dependencies: base64-js: 1.5.1 react-native: 0.71.19(@babel/core@7.25.2)(@babel/preset-env@7.25.4(@babel/core@7.25.2))(encoding@0.1.13)(react@18.3.1) @@ -19446,6 +19523,8 @@ snapshots: ws@8.18.0: {} + ws@8.5.0: {} + x25519-key-agreement-2020-context@1.0.0: {} xcode@3.0.1: From 123ee3eac634d3c1cf61d700f64f1dfe84e158ff Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 25 Nov 2024 15:52:33 +0100 Subject: [PATCH 13/60] refactor: Refactored trust chain resolution --- .../lib/authorization-request/URI.ts | 25 ++++--------------- packages/siop-oid4vp/lib/op/OP.ts | 11 ++++---- packages/siop-oid4vp/lib/op/OPBuilder.ts | 6 ----- packages/siop-oid4vp/package.json | 5 ---- 4 files changed, 10 insertions(+), 37 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/URI.ts b/packages/siop-oid4vp/lib/authorization-request/URI.ts index f1dceb2f..e6e58c50 100644 --- a/packages/siop-oid4vp/lib/authorization-request/URI.ts +++ b/packages/siop-oid4vp/lib/authorization-request/URI.ts @@ -1,5 +1,4 @@ import { parseJWT } from '@sphereon/oid4vc-common' -import { FederationClient, TrustChainResolveResponse } from '@sphereon/openid-federation-client' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { decodeUriAsJson, encodeJsonAsURI, fetchByReferenceOrUseByValue } from '../helpers' @@ -194,8 +193,7 @@ export class URI implements AuthorizationRequestURI { } } else { try { - scheme = - (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' + scheme = (await authorizationRequest.getSupportedVersion()) === SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1 ? 'openid-vc://' : 'openid4vp://' } catch (error: unknown) { scheme = 'openid4vp://' } @@ -236,7 +234,7 @@ export class URI implements AuthorizationRequestURI { return { scheme, authorizationRequestPayload } } - public static async parseAndResolve(uri: string, trustChain?: Array) { + public static async parseAndResolve(uri: string, rpRegistrationMetadata?: RPRegistrationMetadataPayload) { if (!uri) { throw Error(SIOPErrors.BAD_PARAMS) } @@ -244,23 +242,10 @@ export class URI implements AuthorizationRequestURI { const requestObjectJwt = await fetchByReferenceOrUseByValue(authorizationRequestPayload.request_uri, authorizationRequestPayload.request, true) let registrationMetadata: RPRegistrationMetadataPayload - if (trustChain !== undefined && trustChain !== null) { - const fedClient = new FederationClient(null, null) - const resolvedTrustChain: TrustChainResolveResponse = await fedClient.resolveTrustChain( - authorizationRequestPayload['client_metadata_uri'], - trustChain, - ) - if (resolvedTrustChain !== null && resolvedTrustChain !== undefined) { - const clientMetadata = resolvedTrustChain.trustChain.asJsReadonlyArrayView()[1] - const subordinateStatement = JSON.parse(Buffer.from(clientMetadata.split('.')[1]).toString('base64url')) - registrationMetadata = {} - registrationMetadata.federation_entity = subordinateStatement.federationEntity - registrationMetadata.openid_credential_verifier = subordinateStatement.openIdRelyingParty - } else { - throw new Error('Cannot resolve OID Federation metadata') - } + if (rpRegistrationMetadata !== undefined && rpRegistrationMetadata !== null) { + registrationMetadata = rpRegistrationMetadata } else { - registrationMetadata = await fetchByReferenceOrUseByValue( + registrationMetadata = await fetchByReferenceOrUseByValue( authorizationRequestPayload['client_metadata_uri'] ?? authorizationRequestPayload['registration_uri'], authorizationRequestPayload['client_metadata'] ?? authorizationRequestPayload['registration'], ) diff --git a/packages/siop-oid4vp/lib/op/OP.ts b/packages/siop-oid4vp/lib/op/OP.ts index abda723d..87872803 100644 --- a/packages/siop-oid4vp/lib/op/OP.ts +++ b/packages/siop-oid4vp/lib/op/OP.ts @@ -24,13 +24,13 @@ import { RegisterEventListener, RequestObjectPayload, ResponseIss, - ResponseMode, + ResponseMode, RPRegistrationMetadataPayload, SIOPErrors, SupportedVersion, UrlEncodingFormat, Verification, VerifiedAuthorizationRequest -} from '../types'; +} from '../types' import { OPBuilder } from './OPBuilder'; import { createResponseOptsFromBuilderOrExistingOpts, createVerifyRequestOptsFromBuilderOrExistingOpts } from './Opts'; @@ -39,11 +39,9 @@ import { createResponseOptsFromBuilderOrExistingOpts, createVerifyRequestOptsFro export class OP { private readonly _createResponseOptions: AuthorizationResponseOpts private readonly _verifyRequestOptions: Partial - private readonly _trustChain: Array private readonly _eventEmitter?: EventEmitter private constructor(opts: { builder?: OPBuilder; responseOpts?: AuthorizationResponseOpts; verifyOpts?: VerifyAuthorizationRequestOpts }) { - this._trustChain = opts.builder?.trustChain this._createResponseOptions = { ...createResponseOptsFromBuilderOrExistingOpts(opts) } this._verifyRequestOptions = { ...createVerifyRequestOptsFromBuilderOrExistingOpts(opts) } this._eventEmitter = opts.builder?.eventEmitter @@ -276,9 +274,10 @@ export class OP { * Create an Authentication Request Payload from a URI string * * @param encodedUri + * @param rpRegistrationMetadata */ - public async parseAuthorizationRequestURI(encodedUri: string): Promise { - const { scheme, requestObjectJwt, authorizationRequestPayload, registrationMetadata } = await URI.parseAndResolve(encodedUri, this._trustChain) + public async parseAuthorizationRequestURI(encodedUri: string, rpRegistrationMetadata?: RPRegistrationMetadataPayload): Promise { + const { scheme, requestObjectJwt, authorizationRequestPayload, registrationMetadata } = await URI.parseAndResolve(encodedUri, rpRegistrationMetadata) return { encodedUri, diff --git a/packages/siop-oid4vp/lib/op/OPBuilder.ts b/packages/siop-oid4vp/lib/op/OPBuilder.ts index 58d8c0bd..6db8dd54 100644 --- a/packages/siop-oid4vp/lib/op/OPBuilder.ts +++ b/packages/siop-oid4vp/lib/op/OPBuilder.ts @@ -17,7 +17,6 @@ export class OPBuilder { createJwtCallback?: CreateJwtCallback verifyJwtCallback?: VerifyJwtCallback presentationSignCallback?: PresentationSignCallback - trustChain?: Array supportedVersions?: SupportedVersion[] eventEmitter?: EventEmitter @@ -95,11 +94,6 @@ export class OPBuilder { return this } - withTrustChain(trustChain: Array): OPBuilder { - this.trustChain = trustChain - return this - } - withEventEmitter(eventEmitter?: EventEmitter): OPBuilder { this.eventEmitter = eventEmitter ?? new EventEmitter() return this diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index b628e628..15398327 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -81,11 +81,6 @@ "tsimp": "^2.0.11", "typescript": "5.4.5" }, - "peerDependencies": { - "@sphereon/openid-federation-client": "^0.1.1-unstable.21e8440", - "@sphereon/openid-federation-common": "^0.1.1-unstable.21e8440", - "@sphereon/openid-federation-open-api": "^0.1.1-unstable.21e8440" - }, "resolutions": { "isomorphic-webcrypto": "npm:@sphereon/isomorphic-webcrypto@^2.4.1-unstable.0", "esline/**/strip-ansi": "6.0.1" From 4e483a719459e3ee6c4be92868f12b8bac882d56 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 25 Nov 2024 16:15:47 +0100 Subject: [PATCH 14/60] refactor: Removed openid-federation-* dependencies --- packages/client/lib/MetadataClient.ts | 4 +- pnpm-lock.yaml | 78 --------------------------- 2 files changed, 3 insertions(+), 79 deletions(-) diff --git a/packages/client/lib/MetadataClient.ts b/packages/client/lib/MetadataClient.ts index a12caee9..e26a6247 100644 --- a/packages/client/lib/MetadataClient.ts +++ b/packages/client/lib/MetadataClient.ts @@ -60,10 +60,12 @@ export class MetadataClient { /** * Retrieve all metadata from an issuer * @param issuer The issuer URL + * @param credIssuerMetadata * @param opts */ public static async retrieveAllMetadata( issuer: string, + credIssuerMetadata?: CredentialIssuerMetadataV1_0_11 | CredentialIssuerMetadataV1_0_13 | (IssuerMetadataV1_0_08 & Partial), opts?: { errorOnNotFound: boolean }, ): Promise { let token_endpoint: string | undefined; @@ -74,7 +76,7 @@ export class MetadataClient { let authorization_servers: string[] | undefined = [issuer]; let authorization_server: string | undefined = undefined; const oid4vciResponse = await MetadataClient.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations - let credentialIssuerMetadata = oid4vciResponse?.successBody; + let credentialIssuerMetadata = credIssuerMetadata ?? oid4vciResponse?.successBody; if (credentialIssuerMetadata) { debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${JSON.stringify(credentialIssuerMetadata)}`); credential_endpoint = credentialIssuerMetadata.credential_endpoint; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1629032..840cadca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -448,15 +448,6 @@ importers: '@sphereon/oid4vc-common': specifier: workspace:* version: link:../common - '@sphereon/openid-federation-client': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) - '@sphereon/openid-federation-common': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) - '@sphereon/openid-federation-open-api': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) '@sphereon/pex': specifier: 5.0.0-unstable.24 version: 5.0.0-unstable.24 @@ -2103,9 +2094,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@js-joda/core@3.2.0': - resolution: {integrity: sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==} - '@js-joda/core@5.6.3': resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} @@ -2536,15 +2524,6 @@ packages: resolution: {integrity: sha512-uAZZExVy+ug9JLircejWa5eLtAZ7bnBP6xb7DO2+86LRsHNLh2k2jMWJYxp+iWtGHTsh6RYsZl14ScQLvjiQ/A==} bundledDependencies: [] - '@sphereon/openid-federation-client@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-O1CW/t3Zan1wKQxdl6fzDXDrL/t+Ph9UB0rypJA4Pr9u4R+7nB+Z3KC/wphH2Q4NrJFP0sASKn0ER78Gc9onLw==} - - '@sphereon/openid-federation-common@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-mumhjoqeP1qjy3SsT/3AExV+x+SwrO4On+ZrMTFNYjzY7zRKl6rKWkgA0iGbG6z2XR7xW3y1wzDqFxIGS94tXQ==} - - '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-glePGlpbvZI+NhhsfoD44cFbamwIMIQF0xG1k1Ikr9i8XRZFBHz/w/WK9Hfc9dtP63Ry2Ckq8I4KlRZLL5OJ6g==} - '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -5687,9 +5666,6 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} - jose@5.9.4: - resolution: {integrity: sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==} - js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -8526,18 +8502,6 @@ packages: utf-8-validate: optional: true - ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - x25519-key-agreement-2020-context@1.0.0: resolution: {integrity: sha512-zblYd8oSg6hNAD+fA9X7ek1hJQRircl3jVlEVCaBTNN9Mv9b4G32uJvRZFMQEMmda8iaTtYo9i2dRMdXX8pjpA==} @@ -11059,8 +11023,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@js-joda/core@3.2.0': {} - '@js-joda/core@5.6.3': {} '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': @@ -11811,42 +11773,6 @@ snapshots: '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) format-util: 1.0.5 - '@sphereon/openid-federation-client@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - '@js-joda/core': 3.2.0 - abort-controller: 3.0.0 - format-util: 1.0.5 - jose: 5.9.4 - node-fetch: 2.6.12(encoding@0.1.13) - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@sphereon/openid-federation-common@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - abort-controller: 3.0.0 - format-util: 1.0.5 - node-fetch: 2.6.12(encoding@0.1.13) - typescript: 5.5.3 - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - abort-controller: 3.0.0 - format-util: 1.0.5 - node-fetch: 2.6.12(encoding@0.1.13) - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - '@sphereon/pex-models@2.3.1': {} '@sphereon/pex@5.0.0-unstable.24': @@ -16144,8 +16070,6 @@ snapshots: jose@4.15.9: {} - jose@5.9.4: {} - js-base64@3.7.7: {} js-binary-schema-parser@2.0.3: {} @@ -19523,8 +19447,6 @@ snapshots: ws@8.18.0: {} - ws@8.5.0: {} - x25519-key-agreement-2020-context@1.0.0: {} xcode@3.0.1: From 089be8aa7b9ba4eb8d8f75d6ca351ef1aa2e0593 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 25 Nov 2024 16:51:08 +0100 Subject: [PATCH 15/60] refactor: Rolled back the changes, metadata is already present in the constructor of the OpenID4VCIClient's constructor --- packages/client/lib/MetadataClient.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/client/lib/MetadataClient.ts b/packages/client/lib/MetadataClient.ts index fa6ac508..e76f0c0b 100644 --- a/packages/client/lib/MetadataClient.ts +++ b/packages/client/lib/MetadataClient.ts @@ -60,12 +60,10 @@ export class MetadataClient { /** * Retrieve all metadata from an issuer * @param issuer The issuer URL - * @param credIssuerMetadata * @param opts */ public static async retrieveAllMetadata( issuer: string, - credIssuerMetadata?: CredentialIssuerMetadataV1_0_11 | CredentialIssuerMetadataV1_0_13 | (IssuerMetadataV1_0_08 & Partial), opts?: { errorOnNotFound: boolean }, ): Promise { let token_endpoint: string | undefined; @@ -76,7 +74,7 @@ export class MetadataClient { let authorization_servers: string[] | undefined = [issuer]; let authorization_server: string | undefined = undefined; const oid4vciResponse = await MetadataClient.retrieveOpenID4VCIServerMetadata(issuer, { errorOnNotFound: false }); // We will handle errors later, given we will also try other metadata locations - let credentialIssuerMetadata = credIssuerMetadata ?? oid4vciResponse?.successBody; + let credentialIssuerMetadata = oid4vciResponse?.successBody; if (credentialIssuerMetadata) { debug(`Issuer ${issuer} OID4VCI well-known server metadata\r\n${JSON.stringify(credentialIssuerMetadata)}`); credential_endpoint = credentialIssuerMetadata.credential_endpoint; From 38d68ab7df2ccfd6b1327ce067560878fc0f4020 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 25 Nov 2024 17:07:35 +0100 Subject: [PATCH 16/60] refactor: Removed the OIDF types from the library --- .../AuthorizationRequestPayloadVD11.schema.ts | 278 +++--------------- ...ationRequestPayloadVD12OID4VPD18.schema.ts | 278 +++--------------- ...ationRequestPayloadVD12OID4VPD20.schema.ts | 278 +++--------------- .../AuthorizationRequestPayloadVID1.schema.ts | 278 +++--------------- .../RPRegistrationMetadataPayload.schema.ts | 278 +++--------------- packages/siop-oid4vp/lib/types/SIOP.types.ts | 39 +-- 6 files changed, 173 insertions(+), 1256 deletions(-) diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts index f91f842e..020c0299 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts @@ -122,72 +122,6 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "anyOf": [ { @@ -301,38 +235,40 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { } } }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] }, "Format": { "type": "object", @@ -464,152 +400,6 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] - }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts index 5de0ba32..bb6429d1 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts @@ -128,72 +128,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "anyOf": [ { @@ -307,38 +241,40 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { } } }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] }, "Format": { "type": "object", @@ -470,152 +406,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] - }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts index 9312cefe..3a74ad22 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts @@ -128,72 +128,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "anyOf": [ { @@ -307,38 +241,40 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { } } }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] }, "Format": { "type": "object", @@ -470,152 +406,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] - }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts index dcfda501..0b78c774 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts @@ -94,72 +94,6 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "anyOf": [ { @@ -273,38 +207,40 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { } } }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] }, "Format": { "type": "object", @@ -436,152 +372,6 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { ], "additionalProperties": false }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] - }, "ResponseMode": { "type": "string", "enum": [ diff --git a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts index 3d2b5028..f3b2f432 100644 --- a/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/RPRegistrationMetadataPayload.schema.ts @@ -6,72 +6,6 @@ export const RPRegistrationMetadataPayloadSchemaObj = { "RPRegistrationMetadataPayload": { "type": "object", "properties": { - "federation_entity": { - "$ref": "#/definitions/FederationEntityMetadataPayload" - }, - "openid_credential_verifier": { - "type": "object", - "additionalProperties": false, - "properties": { - "vp_formats": { - "$ref": "#/definitions/Format" - }, - "redirect_uris": { - "type": "array", - "items": { - "type": "string" - } - }, - "token_endpoint_auth_method": { - "type": "string" - }, - "grant_types": { - "type": "string" - }, - "response_types": { - "type": "string" - }, - "client_name": { - "type": "string" - }, - "client_uri": { - "type": "string" - }, - "logo_uri": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "contacts": { - "type": "array", - "items": { - "type": "string" - } - }, - "tos_uri": { - "type": "string" - }, - "policy_uri": { - "type": "string" - }, - "jwks_uri": { - "type": "string" - }, - "jwks": { - "$ref": "#/definitions/JWKS" - }, - "software_id": { - "type": "string" - }, - "software_version": { - "type": "string" - } - }, - "required": [ - "vp_formats" - ] - }, "client_id": { "anyOf": [ { @@ -185,38 +119,40 @@ export const RPRegistrationMetadataPayloadSchemaObj = { } } }, - "FederationEntityMetadataPayload": { - "type": "object", - "properties": { - "federation_fetch_endpoint": { - "type": "string" - }, - "federation_list_endpoint": { - "type": "string" - }, - "federation_resolve_endpoint": { - "type": "string" - }, - "federation_trust_mark_status_endpoint": { - "type": "string" - }, - "federation_trust_mark_list_endpoint": { - "type": "string" - }, - "federation_trust_mark_endpoint": { - "type": "string" - }, - "federation_historical_keys_endpoint": { - "type": "string" - }, - "organization_name": { - "type": "string" - }, - "homepage_uri": { - "type": "string" - } - }, - "additionalProperties": false + "SigningAlgo": { + "type": "string", + "enum": [ + "EdDSA", + "RS256", + "PS256", + "ES256", + "ES256K" + ] + }, + "ResponseType": { + "type": "string", + "enum": [ + "id_token", + "vp_token" + ] + }, + "Scope": { + "type": "string", + "enum": [ + "openid", + "openid did_authn", + "profile", + "email", + "address", + "phone" + ] + }, + "SubjectType": { + "type": "string", + "enum": [ + "public", + "pairwise" + ] }, "Format": { "type": "object", @@ -347,152 +283,6 @@ export const RPRegistrationMetadataPayloadSchemaObj = { "alg" ], "additionalProperties": false - }, - "JWKS": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JWK" - } - } - }, - "required": [ - "keys" - ], - "additionalProperties": false - }, - "JWK": { - "type": "object", - "properties": { - "kty": { - "type": "string" - }, - "crv": { - "type": "string" - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - }, - "e": { - "type": "string" - }, - "n": { - "type": "string" - }, - "alg": { - "type": "string" - }, - "d": { - "type": "string" - }, - "dp": { - "type": "string" - }, - "dq": { - "type": "string" - }, - "ext": { - "type": "boolean" - }, - "k": { - "type": "string" - }, - "key_ops": { - "type": "array", - "items": { - "type": "string" - } - }, - "kid": { - "type": "string" - }, - "oth": { - "type": "array", - "items": { - "type": "object", - "properties": { - "d": { - "type": "string" - }, - "r": { - "type": "string" - }, - "t": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "p": { - "type": "string" - }, - "q": { - "type": "string" - }, - "qi": { - "type": "string" - }, - "use": { - "type": "string" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - }, - "additionalProperties": {} - }, - "SigningAlgo": { - "type": "string", - "enum": [ - "EdDSA", - "RS256", - "PS256", - "ES256", - "ES256K" - ] - }, - "ResponseType": { - "type": "string", - "enum": [ - "id_token", - "vp_token" - ] - }, - "Scope": { - "type": "string", - "enum": [ - "openid", - "openid did_authn", - "profile", - "email", - "address", - "phone" - ] - }, - "SubjectType": { - "type": "string", - "enum": [ - "public", - "pairwise" - ] } } }; \ No newline at end of file diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 9071ae14..f9fc0cbc 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -231,40 +231,6 @@ export interface RequestStateInfo { iat?: number } -export interface FederationEntityMetadataPayload { - federation_fetch_endpoint?: string - federation_list_endpoint?: string - federation_resolve_endpoint?: string - federation_trust_mark_status_endpoint?: string - federation_trust_mark_list_endpoint?: string - federation_trust_mark_endpoint?: string - federation_historical_keys_endpoint?: string - organization_name?: string - homepage_uri?: string -} - -export interface FederationEntityMetadataOpts { - federationFetchEndpoint?: string - federationListEndpoint?: string - federationResolveEndpoint?: string - federationTrustMarkStatusEndpoint?: string - federationTrustMarkListEndpoint?: string - federationTrustMarkEndpoint?: string - federationHistoricalKeysEndpoint?: string - organizationName?: string - homepageUri?: string -} - -export type OpenIDCredentialVerifierOpts = { - federationEntity?: FederationEntityMetadataOpts; - openidCredentialVerifier?: DynamicRegistrationClientMetadata & { vp_formats: Format }; -}; - -export type OpenIDCredentialVerifierPayload = { - federation_entity?: FederationEntityMetadataPayload; - openid_credential_verifier?: DynamicRegistrationClientMetadata & { vp_formats: Format }; -}; - interface DiscoveryMetadataCommonOpts { //TODO add the check: Mandatory if PassBy.Value authorizationEndpoint?: Schema | string @@ -308,6 +274,7 @@ interface DiscoveryMetadataCommonOpts { requireRequestUriRegistration?: boolean // from openid connect discovery 1_0 opPolicyUri?: string // from openid connect discovery 1_0 opTosUri?: string // from openid connect discovery 1_0 + // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } @@ -447,7 +414,7 @@ export type RPRegistrationMetadataOpts = Partial< | 'tos_uri' | 'clientPurpose' > -> & OpenIDCredentialVerifierOpts & { +> & { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } @@ -465,7 +432,7 @@ export type RPRegistrationMetadataPayload = Pick< | 'client_name' | 'logo_uri' | 'client_purpose' -> & OpenIDCredentialVerifierPayload & { +> & { // eslint-disable-next-line @typescript-eslint/no-explicit-any [x: string]: any } From 76be4cc85ae2be951574385ba9a6f0aa1c62d18f Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Mon, 25 Nov 2024 14:43:26 +0100 Subject: [PATCH 17/60] fix: update dcql and incorporate feedback --- .../siop-oid4vp/lib/authorization-request/Payload.ts | 4 ++-- .../authorization-response/AuthorizationResponse.ts | 12 +++++------- .../siop-oid4vp/lib/authorization-response/Dcql.ts | 4 ++-- .../lib/authorization-response/OpenID4VP.ts | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 12 ++++++------ 6 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index b21d7c70..07290006 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -35,13 +35,13 @@ export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadO return { ...(opts.id_token ? { id_token: opts.id_token } : {}), - ...((opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri || opts.vp_token.dcql_query) && { + ...((opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri) && { vp_token: { ...(!opts.vp_token.presentation_definition_uri && { presentation_definition: opts.vp_token.presentation_definition }), ...(opts.vp_token.presentation_definition_uri && { presentation_definition_uri: opts.vp_token.presentation_definition_uri }), - ...(opts.vp_token.dcql_query && { dcql_query: opts.vp_token.dcql_query }), }, }), + ...(opts.vp_token.dcql_query && { vp_token: { dcql_query: opts.vp_token.dcql_query } }), } } diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 09d91a6c..9bb0dcf4 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -130,7 +130,7 @@ export class AuthorizationResponse { if (responseOpts.presentationExchange) { const wrappedPresentations = response.payload.vp_token - ? await extractPresentationsFromVpToken(response.payload.vp_token, { + ? extractPresentationsFromVpToken(response.payload.vp_token, { hasher: verifyOpts.hasher, }) : [] @@ -144,14 +144,12 @@ export class AuthorizationResponse { hasher: verifyOpts.hasher, }, }) - } else { - const dcqlQuery = verifiedAuthorizationRequest.dcqlQuery - if (!dcqlQuery) { - throw new Error('vp_token is present, but no presentation definitions or dcql query provided') - } - assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, dcqlQuery, { + } else if (verifiedAuthorizationRequest.dcqlQuery) { + assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, verifiedAuthorizationRequest.dcqlQuery, { hasher: verifyOpts.hasher, }) + } else { + throw new Error('vp_token is present, but no presentation definitions or dcql query provided') } return response diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index 77ab1da5..7740fdb3 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -43,10 +43,10 @@ export const getDcqlPresentationResult = (record: DcqlPresentation | string, dcq if (p.format === 'mso_mdoc') { return [ queryId, - { credentialFormat: 'mso_mdoc', doctype: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential, + { credential_format: 'mso_mdoc', doctype: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential, ] } else if (p.format === 'vc+sd-jwt') { - return [queryId, { credentialFormat: 'vc+sd-jwt', vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] + return [queryId, { credential_format: 'vc+sd-jwt', vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] } else { throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index d1177ef4..d4fe8b9d 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -113,7 +113,7 @@ export const verifyPresentations = async ( } } else { const presentations = authorizationResponse.payload.vp_token - ? await extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) + ? extractPresentationsFromVpToken(authorizationResponse.payload.vp_token, { hasher: verifyOpts.hasher }) : [] wrappedPresentations = Array.isArray(presentations) ? presentations : [presentations] diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 937ce385..acb5d152 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.13", + "dcql": "^0.2.15", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.279", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f4e47bc6..4b704bde 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.13 - version: 0.2.13(typescript@5.4.5) + specifier: ^0.2.15 + version: 0.2.16(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -1867,7 +1867,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {node: '>=0.10.0'} + engines: {'0': node >=0.10.0} '@expo/cli@0.7.3': resolution: {integrity: sha512-uMGHbAhApqXR2sd1KPhgvpbOhBBnspad8msEqHleT2PHXwKIwTUDzBGO9+jdOAWwCx2MJfw3+asYjzoD3DN9Bg==} @@ -4015,8 +4015,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.13: - resolution: {integrity: sha512-XfePsSz9ULj9HH3VFNguzK/xlFnliKDX2iUDb1tIrn97S+TfftcFo+jipw16m9jPlWLhhBx48QniF0D8KotIWA==} + dcql@0.2.16: + resolution: {integrity: sha512-sZpx8QZYc/vdPsOy0PyFWPNmTrDTPyLGsV0wPJJ6u/F+RFkQlw5LHV4fIfzPefdDKUF5YvGm3oDiBt3qzz9/zg==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -13835,7 +13835,7 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.13(typescript@5.4.5): + dcql@0.2.16(typescript@5.4.5): dependencies: valibot: 0.37.0(typescript@5.4.5) transitivePeerDependencies: From d7cc1e7342280370e9a4bef023e1b88ac735f412 Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Tue, 26 Nov 2024 09:59:27 +0100 Subject: [PATCH 18/60] feat: update dcql --- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index acb5d152..fb3df1a0 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "^0.2.15", + "dcql": "0.2.16", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.279", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b704bde..ef85fa2a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,7 +461,7 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: ^0.2.15 + specifier: 0.2.16 version: 0.2.16(typescript@5.4.5) debug: specifier: ^4.3.5 @@ -2535,6 +2535,7 @@ packages: '@sphereon/kmp-mdl-mdoc@0.2.0-SNAPSHOT.22': resolution: {integrity: sha512-uAZZExVy+ug9JLircejWa5eLtAZ7bnBP6xb7DO2+86LRsHNLh2k2jMWJYxp+iWtGHTsh6RYsZl14ScQLvjiQ/A==} + bundledDependencies: [] '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} From ad19797805d68855d902afcf586d521927654adc Mon Sep 17 00:00:00 2001 From: Martin Auer Date: Tue, 26 Nov 2024 10:00:10 +0100 Subject: [PATCH 19/60] feat: update dcql --- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index fb3df1a0..dbe0097d 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.24", - "dcql": "0.2.16", + "dcql": "0.2.17", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-next.279", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef85fa2a..82bfd10d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -461,8 +461,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: 0.2.16 - version: 0.2.16(typescript@5.4.5) + specifier: 0.2.17 + version: 0.2.17(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -4016,8 +4016,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.16: - resolution: {integrity: sha512-sZpx8QZYc/vdPsOy0PyFWPNmTrDTPyLGsV0wPJJ6u/F+RFkQlw5LHV4fIfzPefdDKUF5YvGm3oDiBt3qzz9/zg==} + dcql@0.2.17: + resolution: {integrity: sha512-YKNJR2anEiWooUCg7cJt/QmSFxpBS+SJQurcsNA60+8qUrjOuroh1Wd+lka/yOAV2VUdRzdNY6ISouxTV6SUaQ==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -8322,16 +8322,16 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - valibot@0.37.0: - resolution: {integrity: sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==} + valibot@0.42.1: + resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} peerDependencies: typescript: '>=5' peerDependenciesMeta: typescript: optional: true - valibot@0.42.1: - resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} + valibot@1.0.0-beta.8: + resolution: {integrity: sha512-OPAwJZtowb0j91b+bd77+ny7D1VVzsCzD7Jl9waLUlMprTsfI9Y3HHbW3hAQD7wKDKHsmGEesuiYWaYvcZL2wg==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -13836,9 +13836,9 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.16(typescript@5.4.5): + dcql@0.2.17(typescript@5.4.5): dependencies: - valibot: 0.37.0(typescript@5.4.5) + valibot: 1.0.0-beta.8(typescript@5.4.5) transitivePeerDependencies: - typescript @@ -19309,14 +19309,14 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - valibot@0.37.0(typescript@5.4.5): - optionalDependencies: - typescript: 5.4.5 - valibot@0.42.1(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 + valibot@1.0.0-beta.8(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + valid-url@1.0.9: {} validate-npm-package-license@3.0.4: From 4060fe7f45a12e4eca2a8a321e219ee9ae7d7edf Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 26 Nov 2024 11:17:39 +0100 Subject: [PATCH 20/60] refactor: Added the OIDF client and check to the OID4VCI library --- packages/client/lib/OpenID4VCIClient.ts | 25 +++++++- packages/client/package.json | 5 ++ pnpm-lock.yaml | 79 +++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/OpenID4VCIClient.ts b/packages/client/lib/OpenID4VCIClient.ts index 0ec729d2..90337abd 100644 --- a/packages/client/lib/OpenID4VCIClient.ts +++ b/packages/client/lib/OpenID4VCIClient.ts @@ -1,4 +1,4 @@ -import { CreateDPoPClientOpts, JWK } from '@sphereon/oid4vc-common'; +import { CreateDPoPClientOpts, JWK, parseJWT } from '@sphereon/oid4vc-common'; import { AccessTokenRequestOpts, AccessTokenResponse, @@ -35,6 +35,7 @@ import { ProofOfPossessionCallbacks, toAuthorizationResponsePayload, } from '@sphereon/oid4vci-common'; +import { FederationClient } from '@sphereon/openid-federation-client'; import { CredentialFormat } from '@sphereon/ssi-types'; import Debug from 'debug'; @@ -54,7 +55,9 @@ import { generateMissingPKCEOpts, sendNotification } from './functions'; const debug = Debug('sphereon:oid4vci'); -export type OpenID4VCIClientState = OpenID4VCIClientStateV1_0_11 | OpenID4VCIClientStateV1_0_13; +export type OpenID4VCIClientState = + | (OpenID4VCIClientStateV1_0_11 & { trustChains?: Array }) + | (OpenID4VCIClientStateV1_0_13 & { trustChains?: Array }); export type EndpointMetadataResult = EndpointMetadataResultV1_0_11 | EndpointMetadataResultV1_0_13; @@ -76,6 +79,7 @@ export class OpenID4VCIClient { authorizationRequestOpts, authorizationCodeResponse, authorizationURL, + trustChains, }: { credentialOffer?: CredentialOfferRequestWithBaseUrl; kid?: string; @@ -91,6 +95,7 @@ export class OpenID4VCIClient { authorizationRequestOpts?: AuthorizationRequestOpts; authorizationCodeResponse?: AuthorizationResponse; authorizationURL?: string; + trustChains?: Array; }) { const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined); if (!issuer) { @@ -113,6 +118,7 @@ export class OpenID4VCIClient { : (endpointMetadata as EndpointMetadataResultV1_0_13 | undefined), accessTokenResponse, authorizationURL, + trustChains, } as OpenID4VCIClientState; // Running syncAuthorizationRequestOpts later as it is using the state if (!this._state.authorizationRequestOpts) { @@ -130,6 +136,7 @@ export class OpenID4VCIClient { pkce, authorizationRequest, createAuthorizationRequestURL, + trustChains, }: { credentialIssuer: string; kid?: string; @@ -139,6 +146,7 @@ export class OpenID4VCIClient { createAuthorizationRequestURL?: boolean; authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl pkce?: PKCEOpts; + trustChains?: Array; }) { const client = new OpenID4VCIClient({ kid, @@ -147,6 +155,7 @@ export class OpenID4VCIClient { credentialIssuer, pkce, authorizationRequest, + trustChains, }); if (retrieveServerMetadata === undefined || retrieveServerMetadata) { await client.retrieveServerMetadata(); @@ -257,7 +266,11 @@ export class OpenID4VCIClient { if (this.credentialOffer) { this._state.endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer); } else if (this._state.credentialIssuer) { - this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer); + if (this._state.trustChains !== undefined && this._state.trustChains !== null && this._state.trustChains.length !== 0) { + this._state.endpointMetadata = await this.retrieveTrustChainMetadata(this._state.credentialIssuer, this._state.trustChains); + } else { + this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer); + } } else { throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`); } @@ -266,6 +279,12 @@ export class OpenID4VCIClient { return this.endpointMetadata; } + private async retrieveTrustChainMetadata(credentialIssuer: string, trustChains: Array): Promise { + const oidfClient = new FederationClient(null, null); + const resolvedTrustChain = await oidfClient.resolveTrustChain(credentialIssuer, trustChains); + return resolvedTrustChain?.trustChain?.asJsReadonlyArrayView().map((s) => parseJWT(s))[1].payload as EndpointMetadataResult | undefined; + } + private calculatePKCEOpts(pkce?: PKCEOpts) { this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce }); } diff --git a/packages/client/package.json b/packages/client/package.json index 42c78f5f..abb569e3 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -47,6 +47,11 @@ "uint8arrays": "3.1.1", "uuid": "^9.0.1" }, + "peerDependencies": { + "@sphereon/openid-federation-client": "^0.1.1-unstable.21e8440", + "@sphereon/openid-federation-common": "^0.1.1-unstable.21e8440", + "@sphereon/openid-federation-open-api": "^0.1.1-unstable.21e8440" + }, "engines": { "node": ">=18" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ac67b6b..5786947b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,6 +118,15 @@ importers: '@sphereon/oid4vci-common': specifier: workspace:* version: link:../oid4vci-common + '@sphereon/openid-federation-client': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) + '@sphereon/openid-federation-common': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) + '@sphereon/openid-federation-open-api': + specifier: ^0.1.1-unstable.21e8440 + version: 0.1.1-unstable.21e8440(encoding@0.1.13) '@sphereon/ssi-types': specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 @@ -2116,6 +2125,9 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@js-joda/core@3.2.0': + resolution: {integrity: sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==} + '@js-joda/core@5.6.3': resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} @@ -2542,6 +2554,16 @@ packages: '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.10': resolution: {integrity: sha512-mHH7I6fWdztaNjguGJOLaerXWnQymQ/xKQ8NqClIXoI2PJNgmpQG6DxFcLRs1aYyWg1iY8bPliLJi41u94KdCA==} + bundledDependencies: [] + + '@sphereon/openid-federation-client@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-O1CW/t3Zan1wKQxdl6fzDXDrL/t+Ph9UB0rypJA4Pr9u4R+7nB+Z3KC/wphH2Q4NrJFP0sASKn0ER78Gc9onLw==} + + '@sphereon/openid-federation-common@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-mumhjoqeP1qjy3SsT/3AExV+x+SwrO4On+ZrMTFNYjzY7zRKl6rKWkgA0iGbG6z2XR7xW3y1wzDqFxIGS94tXQ==} + + '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440': + resolution: {integrity: sha512-glePGlpbvZI+NhhsfoD44cFbamwIMIQF0xG1k1Ikr9i8XRZFBHz/w/WK9Hfc9dtP63Ry2Ckq8I4KlRZLL5OJ6g==} '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -5716,6 +5738,9 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + jose@5.9.4: + resolution: {integrity: sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==} + js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -8601,6 +8626,18 @@ packages: utf-8-validate: optional: true + ws@8.5.0: + resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + x25519-key-agreement-2020-context@1.0.0: resolution: {integrity: sha512-zblYd8oSg6hNAD+fA9X7ek1hJQRircl3jVlEVCaBTNN9Mv9b4G32uJvRZFMQEMmda8iaTtYo9i2dRMdXX8pjpA==} @@ -11142,6 +11179,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@js-joda/core@3.2.0': {} + '@js-joda/core@5.6.3': {} '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': @@ -11878,6 +11917,42 @@ snapshots: '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) format-util: 1.0.5 + '@sphereon/openid-federation-client@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + '@js-joda/core': 3.2.0 + abort-controller: 3.0.0 + format-util: 1.0.5 + jose: 5.9.4 + node-fetch: 2.6.12(encoding@0.1.13) + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + + '@sphereon/openid-federation-common@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + abort-controller: 3.0.0 + format-util: 1.0.5 + node-fetch: 2.6.12(encoding@0.1.13) + typescript: 5.5.3 + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + + '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440(encoding@0.1.13)': + dependencies: + abort-controller: 3.0.0 + format-util: 1.0.5 + node-fetch: 2.6.12(encoding@0.1.13) + ws: 8.5.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + '@sphereon/pex-models@2.3.1': {} '@sphereon/pex@5.0.0-unstable.28': @@ -16301,6 +16376,8 @@ snapshots: jose@4.15.9: {} + jose@5.9.4: {} + js-base64@3.7.7: {} js-binary-schema-parser@2.0.3: {} @@ -19772,6 +19849,8 @@ snapshots: ws@8.18.0: {} + ws@8.5.0: {} + x25519-key-agreement-2020-context@1.0.0: {} xcode@3.0.1: From e04c3d13ca616e4168d4d7d84a22762a02f35c8f Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 26 Nov 2024 12:58:50 +0100 Subject: [PATCH 21/60] refactor: Removed the OIDF library and added the client metadata to the constructor functions --- packages/client/lib/OpenID4VCIClient.ts | 31 +++++++------------------ packages/client/package.json | 5 ---- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/packages/client/lib/OpenID4VCIClient.ts b/packages/client/lib/OpenID4VCIClient.ts index 90337abd..3125208f 100644 --- a/packages/client/lib/OpenID4VCIClient.ts +++ b/packages/client/lib/OpenID4VCIClient.ts @@ -1,4 +1,4 @@ -import { CreateDPoPClientOpts, JWK, parseJWT } from '@sphereon/oid4vc-common'; +import { CreateDPoPClientOpts, JWK } from '@sphereon/oid4vc-common'; import { AccessTokenRequestOpts, AccessTokenResponse, @@ -35,7 +35,6 @@ import { ProofOfPossessionCallbacks, toAuthorizationResponsePayload, } from '@sphereon/oid4vci-common'; -import { FederationClient } from '@sphereon/openid-federation-client'; import { CredentialFormat } from '@sphereon/ssi-types'; import Debug from 'debug'; @@ -55,9 +54,7 @@ import { generateMissingPKCEOpts, sendNotification } from './functions'; const debug = Debug('sphereon:oid4vci'); -export type OpenID4VCIClientState = - | (OpenID4VCIClientStateV1_0_11 & { trustChains?: Array }) - | (OpenID4VCIClientStateV1_0_13 & { trustChains?: Array }); +export type OpenID4VCIClientState = OpenID4VCIClientStateV1_0_11 | OpenID4VCIClientStateV1_0_13; export type EndpointMetadataResult = EndpointMetadataResultV1_0_11 | EndpointMetadataResultV1_0_13; @@ -79,7 +76,6 @@ export class OpenID4VCIClient { authorizationRequestOpts, authorizationCodeResponse, authorizationURL, - trustChains, }: { credentialOffer?: CredentialOfferRequestWithBaseUrl; kid?: string; @@ -95,7 +91,6 @@ export class OpenID4VCIClient { authorizationRequestOpts?: AuthorizationRequestOpts; authorizationCodeResponse?: AuthorizationResponse; authorizationURL?: string; - trustChains?: Array; }) { const issuer = credentialIssuer ?? (credentialOffer ? getIssuerFromCredentialOfferPayload(credentialOffer.credential_offer) : undefined); if (!issuer) { @@ -118,7 +113,6 @@ export class OpenID4VCIClient { : (endpointMetadata as EndpointMetadataResultV1_0_13 | undefined), accessTokenResponse, authorizationURL, - trustChains, } as OpenID4VCIClientState; // Running syncAuthorizationRequestOpts later as it is using the state if (!this._state.authorizationRequestOpts) { @@ -136,7 +130,7 @@ export class OpenID4VCIClient { pkce, authorizationRequest, createAuthorizationRequestURL, - trustChains, + endpointMetadata }: { credentialIssuer: string; kid?: string; @@ -146,7 +140,7 @@ export class OpenID4VCIClient { createAuthorizationRequestURL?: boolean; authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl pkce?: PKCEOpts; - trustChains?: Array; + endpointMetadata?: EndpointMetadataResult }) { const client = new OpenID4VCIClient({ kid, @@ -155,7 +149,7 @@ export class OpenID4VCIClient { credentialIssuer, pkce, authorizationRequest, - trustChains, + endpointMetadata }); if (retrieveServerMetadata === undefined || retrieveServerMetadata) { await client.retrieveServerMetadata(); @@ -182,6 +176,7 @@ export class OpenID4VCIClient { createAuthorizationRequestURL, authorizationRequest, resolveOfferUri, + endpointMetadata }: { uri: string; kid?: string; @@ -192,6 +187,7 @@ export class OpenID4VCIClient { pkce?: PKCEOpts; clientId?: string; authorizationRequest?: AuthorizationRequestOpts; // Can be provided here, or when manually calling createAuthorizationUrl + endpointMetadata?: EndpointMetadataResult }): Promise { const credentialOfferClient = await CredentialOfferClient.fromURI(uri, { resolve: resolveOfferUri }); const client = new OpenID4VCIClient({ @@ -201,6 +197,7 @@ export class OpenID4VCIClient { clientId: clientId ?? authorizationRequest?.clientId ?? credentialOfferClient.clientId, pkce, authorizationRequest, + endpointMetadata }); if (retrieveServerMetadata === undefined || retrieveServerMetadata) { @@ -266,11 +263,7 @@ export class OpenID4VCIClient { if (this.credentialOffer) { this._state.endpointMetadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(this.credentialOffer); } else if (this._state.credentialIssuer) { - if (this._state.trustChains !== undefined && this._state.trustChains !== null && this._state.trustChains.length !== 0) { - this._state.endpointMetadata = await this.retrieveTrustChainMetadata(this._state.credentialIssuer, this._state.trustChains); - } else { - this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer); - } + this._state.endpointMetadata = await MetadataClient.retrieveAllMetadata(this._state.credentialIssuer); } else { throw Error(`Cannot retrieve issuer metadata without either a credential offer, or issuer value`); } @@ -279,12 +272,6 @@ export class OpenID4VCIClient { return this.endpointMetadata; } - private async retrieveTrustChainMetadata(credentialIssuer: string, trustChains: Array): Promise { - const oidfClient = new FederationClient(null, null); - const resolvedTrustChain = await oidfClient.resolveTrustChain(credentialIssuer, trustChains); - return resolvedTrustChain?.trustChain?.asJsReadonlyArrayView().map((s) => parseJWT(s))[1].payload as EndpointMetadataResult | undefined; - } - private calculatePKCEOpts(pkce?: PKCEOpts) { this._state.pkce = generateMissingPKCEOpts({ ...this._state.pkce, ...pkce }); } diff --git a/packages/client/package.json b/packages/client/package.json index abb569e3..42c78f5f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -47,11 +47,6 @@ "uint8arrays": "3.1.1", "uuid": "^9.0.1" }, - "peerDependencies": { - "@sphereon/openid-federation-client": "^0.1.1-unstable.21e8440", - "@sphereon/openid-federation-common": "^0.1.1-unstable.21e8440", - "@sphereon/openid-federation-open-api": "^0.1.1-unstable.21e8440" - }, "engines": { "node": ">=18" }, From 38171979d9e64a8c454122f20e3099a270ef25cc Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 26 Nov 2024 13:11:49 +0100 Subject: [PATCH 22/60] refactor: Updated pnpm-lock.yaml --- pnpm-lock.yaml | 78 -------------------------------------------------- 1 file changed, 78 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5786947b..2b2bb1dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,15 +118,6 @@ importers: '@sphereon/oid4vci-common': specifier: workspace:* version: link:../oid4vci-common - '@sphereon/openid-federation-client': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) - '@sphereon/openid-federation-common': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) - '@sphereon/openid-federation-open-api': - specifier: ^0.1.1-unstable.21e8440 - version: 0.1.1-unstable.21e8440(encoding@0.1.13) '@sphereon/ssi-types': specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 @@ -2125,9 +2116,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@js-joda/core@3.2.0': - resolution: {integrity: sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==} - '@js-joda/core@5.6.3': resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} @@ -2556,15 +2544,6 @@ packages: resolution: {integrity: sha512-mHH7I6fWdztaNjguGJOLaerXWnQymQ/xKQ8NqClIXoI2PJNgmpQG6DxFcLRs1aYyWg1iY8bPliLJi41u94KdCA==} bundledDependencies: [] - '@sphereon/openid-federation-client@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-O1CW/t3Zan1wKQxdl6fzDXDrL/t+Ph9UB0rypJA4Pr9u4R+7nB+Z3KC/wphH2Q4NrJFP0sASKn0ER78Gc9onLw==} - - '@sphereon/openid-federation-common@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-mumhjoqeP1qjy3SsT/3AExV+x+SwrO4On+ZrMTFNYjzY7zRKl6rKWkgA0iGbG6z2XR7xW3y1wzDqFxIGS94tXQ==} - - '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440': - resolution: {integrity: sha512-glePGlpbvZI+NhhsfoD44cFbamwIMIQF0xG1k1Ikr9i8XRZFBHz/w/WK9Hfc9dtP63Ry2Ckq8I4KlRZLL5OJ6g==} - '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -5738,9 +5717,6 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} - jose@5.9.4: - resolution: {integrity: sha512-WBBl6au1qg6OHj67yCffCgFR3BADJBXN8MdRvCgJDuMv3driV2nHr7jdGvaKX9IolosAsn+M0XRArqLXUhyJHQ==} - js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -8626,18 +8602,6 @@ packages: utf-8-validate: optional: true - ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - x25519-key-agreement-2020-context@1.0.0: resolution: {integrity: sha512-zblYd8oSg6hNAD+fA9X7ek1hJQRircl3jVlEVCaBTNN9Mv9b4G32uJvRZFMQEMmda8iaTtYo9i2dRMdXX8pjpA==} @@ -11179,8 +11143,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@js-joda/core@3.2.0': {} - '@js-joda/core@5.6.3': {} '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': @@ -11917,42 +11879,6 @@ snapshots: '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) format-util: 1.0.5 - '@sphereon/openid-federation-client@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - '@js-joda/core': 3.2.0 - abort-controller: 3.0.0 - format-util: 1.0.5 - jose: 5.9.4 - node-fetch: 2.6.12(encoding@0.1.13) - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@sphereon/openid-federation-common@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - abort-controller: 3.0.0 - format-util: 1.0.5 - node-fetch: 2.6.12(encoding@0.1.13) - typescript: 5.5.3 - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - '@sphereon/openid-federation-open-api@0.1.1-unstable.21e8440(encoding@0.1.13)': - dependencies: - abort-controller: 3.0.0 - format-util: 1.0.5 - node-fetch: 2.6.12(encoding@0.1.13) - ws: 8.5.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - '@sphereon/pex-models@2.3.1': {} '@sphereon/pex@5.0.0-unstable.28': @@ -16376,8 +16302,6 @@ snapshots: jose@4.15.9: {} - jose@5.9.4: {} - js-base64@3.7.7: {} js-binary-schema-parser@2.0.3: {} @@ -19849,8 +19773,6 @@ snapshots: ws@8.18.0: {} - ws@8.5.0: {} - x25519-key-agreement-2020-context@1.0.0: {} xcode@3.0.1: From 33e0be728e0cee17be59066818957c668587e2ed Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Thu, 5 Dec 2024 11:41:53 +0100 Subject: [PATCH 23/60] chore: Added dcql to resolutions since there are major changes in the API. --- package.json | 1 + packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9339e342..762975d3 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "resolutions": { "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "dcql": "0.2.11", "node-fetch": "2.6.12" }, "prettier": { diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index a7d71c96..a1aae703 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.28", - "dcql": "^0.2.11", + "dcql": "0.2.11", "@sphereon/pex-models": "^2.3.1", "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ac67b6b..52d346bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ settings: overrides: '@sphereon/ssi-types': 0.30.2-feature.mdoc.funke2.367 + dcql: 0.2.11 node-fetch: 2.6.12 importers: @@ -461,6 +462,9 @@ importers: cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) + dcql: + specifier: 0.2.11 + version: 0.2.11(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -2542,6 +2546,7 @@ packages: '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.10': resolution: {integrity: sha512-mHH7I6fWdztaNjguGJOLaerXWnQymQ/xKQ8NqClIXoI2PJNgmpQG6DxFcLRs1aYyWg1iY8bPliLJi41u94KdCA==} + bundledDependencies: [] '@sphereon/pex-models@2.3.1': resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} @@ -4013,6 +4018,9 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dcql@0.2.11: + resolution: {integrity: sha512-hR8MuSx49b7JPoZztcFMSKEHc6iEE4l/Zs6aUsvMCWVa3qFWpuJRiJEp5Rh2+UkCAhsce94fbDpMdBTcS9zn7g==} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -8372,6 +8380,14 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + valibot@0.37.0: + resolution: {integrity: sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + valibot@0.42.1: resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} peerDependencies: @@ -13898,6 +13914,12 @@ snapshots: dayjs@1.11.13: {} + dcql@0.2.11(typescript@5.4.5): + dependencies: + valibot: 0.37.0(typescript@5.4.5) + transitivePeerDependencies: + - typescript + debug@2.6.9: dependencies: ms: 2.0.0 @@ -19558,6 +19580,10 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + valibot@0.37.0(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + valibot@0.42.1(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 From 10fd2b1c4dcd919faeb643bab7b622f8eef73873 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 9 Dec 2024 14:33:19 +0100 Subject: [PATCH 24/60] chore: Fixed broken dependencies --- package.json | 2 +- packages/callback-example/package.json | 2 +- packages/client/package.json | 2 +- packages/common/package.json | 2 +- packages/issuer-rest/package.json | 2 +- packages/issuer/package.json | 2 +- packages/oid4vci-common/package.json | 2 +- .../AuthorizationRequestPayloadVD11.schema.ts | 82 +---------------- ...ationRequestPayloadVD12OID4VPD18.schema.ts | 82 +---------------- ...ationRequestPayloadVD12OID4VPD20.schema.ts | 82 +---------------- .../AuthorizationRequestPayloadVID1.schema.ts | 82 +---------------- packages/siop-oid4vp/package.json | 4 +- pnpm-lock.yaml | 91 +++++-------------- 13 files changed, 52 insertions(+), 385 deletions(-) diff --git a/package.json b/package.json index 762975d3..3eccf5f6 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node": ">=18" }, "resolutions": { - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../SSI-SDK/packages/ssi-types", "dcql": "0.2.11", "node-fetch": "2.6.12" }, diff --git a/packages/callback-example/package.json b/packages/callback-example/package.json index 515af167..64c6ffd9 100644 --- a/packages/callback-example/package.json +++ b/packages/callback-example/package.json @@ -19,7 +19,7 @@ "@sphereon/oid4vci-client": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "jose": "^4.10.0" }, "devDependencies": { diff --git a/packages/client/package.json b/packages/client/package.json index 42c78f5f..cb1db4dc 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,7 +17,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "cross-fetch": "^3.1.8", "debug": "^4.3.5" }, diff --git a/packages/common/package.json b/packages/common/package.json index 2f134698..fe28aac1 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -10,7 +10,7 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "jwt-decode": "^4.0.0", "sha.js": "^2.4.11", "uint8arrays": "3.1.1", diff --git a/packages/issuer-rest/package.json b/packages/issuer-rest/package.json index 909e1f0e..f06fb058 100644 --- a/packages/issuer-rest/package.json +++ b/packages/issuer-rest/package.json @@ -15,7 +15,7 @@ "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", "@sphereon/ssi-express-support": "0.30.2-feature.mdoc.funke2.367", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", diff --git a/packages/issuer/package.json b/packages/issuer/package.json index ea56dee2..2b5b6934 100644 --- a/packages/issuer/package.json +++ b/packages/issuer/package.json @@ -12,7 +12,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "uuid": "^9.0.0" }, "peerDependencies": { diff --git a/packages/oid4vci-common/package.json b/packages/oid4vci-common/package.json index 285a6a31..d7731797 100644 --- a/packages/oid4vci-common/package.json +++ b/packages/oid4vci-common/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@sphereon/oid4vc-common": "workspace:*", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "cross-fetch": "^3.1.8", "debug": "^4.3.5", "jwt-decode": "^4.0.0", diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts index 020c0299..0fb7ce3a 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD11.schema.ts @@ -699,9 +699,6 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { "type": "string" } }, - "required": [ - "type" - ], "additionalProperties": false }, "OneOfNumberStringBoolean": { @@ -934,81 +931,15 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" - }, - "items": { - "$ref": "#/definitions/FilterV2BaseItems" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "FilterV2Base": { - "type": "object", - "properties": { - "const": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - }, - "enum": { - "type": "array", - "items": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - } - }, - "exclusiveMinimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "format": { - "type": "string" - }, - "formatMaximum": { - "type": "string" - }, - "formatMinimum": { - "type": "string" - }, - "formatExclusiveMaximum": { - "type": "string" - }, - "formatExclusiveMinimum": { - "type": "string" - }, - "minLength": { - "type": "number" - }, - "maxLength": { - "type": "number" - }, - "minimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "maximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "not": { - "type": "object" - }, - "pattern": { - "type": "string" - }, - "type": { - "type": "string" - }, - "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, "additionalProperties": false }, - "FilterV2BaseItems": { + "FilterV2Items": { "type": "object", "properties": { "const": { @@ -1063,15 +994,12 @@ export const AuthorizationRequestPayloadVD11SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, - "required": [ - "type" - ], "additionalProperties": false } } diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts index bb6429d1..3191b080 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD18.schema.ts @@ -705,9 +705,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { "type": "string" } }, - "required": [ - "type" - ], "additionalProperties": false }, "OneOfNumberStringBoolean": { @@ -940,81 +937,15 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" - }, - "items": { - "$ref": "#/definitions/FilterV2BaseItems" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "FilterV2Base": { - "type": "object", - "properties": { - "const": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - }, - "enum": { - "type": "array", - "items": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - } - }, - "exclusiveMinimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "format": { - "type": "string" - }, - "formatMaximum": { - "type": "string" - }, - "formatMinimum": { - "type": "string" - }, - "formatExclusiveMaximum": { - "type": "string" - }, - "formatExclusiveMinimum": { - "type": "string" - }, - "minLength": { - "type": "number" - }, - "maxLength": { - "type": "number" - }, - "minimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "maximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "not": { - "type": "object" - }, - "pattern": { - "type": "string" - }, - "type": { - "type": "string" - }, - "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, "additionalProperties": false }, - "FilterV2BaseItems": { + "FilterV2Items": { "type": "object", "properties": { "const": { @@ -1069,15 +1000,12 @@ export const AuthorizationRequestPayloadVD12OID4VPD18SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, - "required": [ - "type" - ], "additionalProperties": false }, "ClientIdSchemeOID4VPD18": { diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts index 14e4d863..eeee9e8a 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVD12OID4VPD20.schema.ts @@ -708,9 +708,6 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { "type": "string" } }, - "required": [ - "type" - ], "additionalProperties": false }, "OneOfNumberStringBoolean": { @@ -943,81 +940,15 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" - }, - "items": { - "$ref": "#/definitions/FilterV2BaseItems" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "FilterV2Base": { - "type": "object", - "properties": { - "const": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - }, - "enum": { - "type": "array", - "items": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - } - }, - "exclusiveMinimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "format": { - "type": "string" - }, - "formatMaximum": { - "type": "string" - }, - "formatMinimum": { - "type": "string" - }, - "formatExclusiveMaximum": { - "type": "string" - }, - "formatExclusiveMinimum": { - "type": "string" - }, - "minLength": { - "type": "number" - }, - "maxLength": { - "type": "number" - }, - "minimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "maximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "not": { - "type": "object" - }, - "pattern": { - "type": "string" - }, - "type": { - "type": "string" - }, - "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, "additionalProperties": false }, - "FilterV2BaseItems": { + "FilterV2Items": { "type": "object", "properties": { "const": { @@ -1072,15 +1003,12 @@ export const AuthorizationRequestPayloadVD12OID4VPD20SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, - "required": [ - "type" - ], "additionalProperties": false }, "ClientIdSchemeOID4VPD20": { diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts index 59cc00bf..61931b35 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationRequestPayloadVID1.schema.ts @@ -704,9 +704,6 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { "type": "string" } }, - "required": [ - "type" - ], "additionalProperties": false }, "OneOfNumberStringBoolean": { @@ -939,81 +936,15 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" - }, - "items": { - "$ref": "#/definitions/FilterV2BaseItems" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - }, - "FilterV2Base": { - "type": "object", - "properties": { - "const": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - }, - "enum": { - "type": "array", - "items": { - "$ref": "#/definitions/OneOfNumberStringBoolean" - } - }, - "exclusiveMinimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "format": { - "type": "string" - }, - "formatMaximum": { - "type": "string" - }, - "formatMinimum": { - "type": "string" - }, - "formatExclusiveMaximum": { - "type": "string" - }, - "formatExclusiveMinimum": { - "type": "string" - }, - "minLength": { - "type": "number" - }, - "maxLength": { - "type": "number" - }, - "minimum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "maximum": { - "$ref": "#/definitions/OneOfNumberString" - }, - "not": { - "type": "object" - }, - "pattern": { - "type": "string" - }, - "type": { - "type": "string" - }, - "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, "additionalProperties": false }, - "FilterV2BaseItems": { + "FilterV2Items": { "type": "object", "properties": { "const": { @@ -1068,15 +999,12 @@ export const AuthorizationRequestPayloadVID1SchemaObj = { "type": "string" }, "contains": { - "$ref": "#/definitions/FilterV2Base" + "$ref": "#/definitions/FilterV2" }, "items": { - "$ref": "#/definitions/FilterV2BaseItems" + "$ref": "#/definitions/FilterV2Items" } }, - "required": [ - "type" - ], "additionalProperties": false } } diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index a1aae703..9c317640 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -19,8 +19,8 @@ "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.28", "dcql": "0.2.11", - "@sphereon/pex-models": "^2.3.1", - "@sphereon/ssi-types": "0.30.2-feature.mdoc.funke2.367", + "@sphereon/pex-models": "^2.3.2", + "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", "cross-fetch": "^4.0.0", "debug": "^4.3.5", "events": "^3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52d346bb..6e6aadee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: - '@sphereon/ssi-types': 0.30.2-feature.mdoc.funke2.367 + '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types dcql: 0.2.11 node-fetch: 2.6.12 @@ -77,8 +77,8 @@ importers: specifier: workspace:* version: link:../issuer '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types jose: specifier: ^4.10.0 version: 4.15.9 @@ -120,8 +120,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -205,8 +205,8 @@ importers: packages/common: dependencies: '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -273,8 +273,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -316,8 +316,8 @@ importers: specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -408,8 +408,8 @@ importers: specifier: workspace:* version: link:../common '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -454,11 +454,11 @@ importers: specifier: 5.0.0-unstable.28 version: 5.0.0-unstable.28 '@sphereon/pex-models': - specifier: ^2.3.1 - version: 2.3.1 + specifier: ^2.3.2 + version: 2.3.2 '@sphereon/ssi-types': - specifier: 0.30.2-feature.mdoc.funke2.367 - version: 0.30.2-feature.mdoc.funke2.367 + specifier: link:../../../SSI-SDK/packages/ssi-types + version: link:../../../SSI-SDK/packages/ssi-types cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -2120,14 +2120,6 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@js-joda/core@5.6.3': - resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} - - '@js-joda/timezone@2.3.0': - resolution: {integrity: sha512-DHXdNs0SydSqC5f0oRJPpTcNfnpRojgBqMCFupQFv6WgeZAjU3DBx+A7JtaGPP3dHrP2Odi2N8Vf+uAm/8ynCQ==} - peerDependencies: - '@js-joda/core': '>=1.11.0' - '@lerna/create@8.1.9': resolution: {integrity: sha512-DPnl5lPX4v49eVxEbJnAizrpMdMTBz1qykZrAbBul9rfgk531v8oAt+Pm6O/rpAleRombNM7FJb5rYGzBJatOQ==} engines: {node: '>=18.0.0'} @@ -2544,12 +2536,8 @@ packages: react-native-securerandom: optional: true - '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.10': - resolution: {integrity: sha512-mHH7I6fWdztaNjguGJOLaerXWnQymQ/xKQ8NqClIXoI2PJNgmpQG6DxFcLRs1aYyWg1iY8bPliLJi41u94KdCA==} - bundledDependencies: [] - - '@sphereon/pex-models@2.3.1': - resolution: {integrity: sha512-SByU4cJ0XYA6VZQ/L6lsSiRcFtBPHbFioCeQ4GP7/W/jQ+PSBD7uK2oTnKQ9/0iEiMK/6JYqhKgLs4a9UX3UTQ==} + '@sphereon/pex-models@2.3.2': + resolution: {integrity: sha512-foFxfLkRwcn/MOp/eht46Q7wsvpQGlO7aowowIIb5Tz9u97kYZ2kz6K2h2ODxWuv5CRA7Q0MY8XUBGE2lfOhOQ==} '@sphereon/pex@5.0.0-unstable.28': resolution: {integrity: sha512-zxHCWAc7fKppS7XX0zxnI4TF+Rdjax8pHc3exrYzn3t59dlv5siEAeYdtFrWJT4UVB5wTGzIEufzV5r+tfjelg==} @@ -2572,9 +2560,6 @@ packages: '@sphereon/ssi-sdk-ext.key-utils@0.23.0': resolution: {integrity: sha512-BfULXvQmcUrBq2DqYxJHKnEoB2d5icu3TJ9GP2aP1WybSULTjL96Wv5r7QKgktcodKaL+F+oQ7r8sC9qBl1exw==} - '@sphereon/ssi-types@0.30.2-feature.mdoc.funke2.367': - resolution: {integrity: sha512-+acZDnAB08PjhrNX+0sJuGK6X3AN2zZ6dvXjfWCXovWjJwcKJBBGR+nfvguBbefR9aaB8SKPAkDFhQ/U/I7byg==} - '@sphereon/wellknown-dids-client@0.1.3': resolution: {integrity: sha512-TAT24L3RoXD8ocrkTcsz7HuJmgjNjdoV6IXP1p3DdaI/GqkynytXE3J1+F7vUFMRYwY5nW2RaXSgDQhrFJemaA==} @@ -4774,9 +4759,6 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} - format-util@1.0.5: - resolution: {integrity: sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==} - formidable@2.1.2: resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} @@ -11158,12 +11140,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@js-joda/core@5.6.3': {} - - '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': - dependencies: - '@js-joda/core': 5.6.3 - '@lerna/create@8.1.9(encoding@0.1.13)(typescript@5.5.3)': dependencies: '@npmcli/arborist': 7.5.4 @@ -11888,13 +11864,7 @@ snapshots: expo: 48.0.21(@babel/core@7.26.0)(encoding@0.1.13) react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) - '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.10': - dependencies: - '@js-joda/core': 5.6.3 - '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) - format-util: 1.0.5 - - '@sphereon/pex-models@2.3.1': {} + '@sphereon/pex-models@2.3.2': {} '@sphereon/pex@5.0.0-unstable.28': dependencies: @@ -11902,15 +11872,13 @@ snapshots: '@sd-jwt/decode': 0.7.2 '@sd-jwt/present': 0.7.2 '@sd-jwt/types': 0.7.2 - '@sphereon/pex-models': 2.3.1 - '@sphereon/ssi-types': 0.30.2-feature.mdoc.funke2.367 + '@sphereon/pex-models': 2.3.2 + '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types ajv: 8.17.1 ajv-formats: 2.1.1(ajv@8.17.1) jwt-decode: 3.1.2 nanoid: 3.3.7 uint8arrays: 3.1.1 - transitivePeerDependencies: - - supports-color '@sphereon/ssi-express-support@0.30.2-feature.mdoc.funke2.367': dependencies: @@ -11955,24 +11923,13 @@ snapshots: - react-native-securerandom - supports-color - '@sphereon/ssi-types@0.30.2-feature.mdoc.funke2.367': - dependencies: - '@sd-jwt/decode': 0.7.2 - '@sphereon/kmp-mdoc-core': 0.2.0-SNAPSHOT.10 - debug: 4.3.7 - events: 3.3.0 - jwt-decode: 3.1.2 - transitivePeerDependencies: - - supports-color - '@sphereon/wellknown-dids-client@0.1.3(encoding@0.1.13)': dependencies: - '@sphereon/ssi-types': 0.30.2-feature.mdoc.funke2.367 + '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types cross-fetch: 3.1.8(encoding@0.1.13) jwt-decode: 3.1.2 transitivePeerDependencies: - encoding - - supports-color '@stablelib/aead@1.0.1': {} @@ -14981,8 +14938,6 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - format-util@1.0.5: {} - formidable@2.1.2: dependencies: dezalgo: 1.0.4 From fc238f42e2a1a3427af82385b61cbdc2485bac31 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 11 Dec 2024 16:11:13 +0100 Subject: [PATCH 25/60] refactor: Removed local dependencies --- package.json | 5 +- packages/callback-example/package.json | 2 +- packages/client/package.json | 2 +- packages/common/package.json | 2 +- packages/issuer-rest/package.json | 2 +- packages/issuer/package.json | 2 +- packages/oid4vci-common/package.json | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 80 ++++++++++++++++++++------ 9 files changed, 73 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 3eccf5f6..3fb16fb7 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node": ">=18" }, "resolutions": { - "@sphereon/ssi-types": "link:../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "dcql": "0.2.11", "node-fetch": "2.6.12" }, @@ -65,5 +65,6 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ] + ], + "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" } diff --git a/packages/callback-example/package.json b/packages/callback-example/package.json index 64c6ffd9..2b771138 100644 --- a/packages/callback-example/package.json +++ b/packages/callback-example/package.json @@ -19,7 +19,7 @@ "@sphereon/oid4vci-client": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "jose": "^4.10.0" }, "devDependencies": { diff --git a/packages/client/package.json b/packages/client/package.json index cb1db4dc..9617ba91 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,7 +17,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "cross-fetch": "^3.1.8", "debug": "^4.3.5" }, diff --git a/packages/common/package.json b/packages/common/package.json index fe28aac1..e7a0f0d8 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -10,7 +10,7 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "jwt-decode": "^4.0.0", "sha.js": "^2.4.11", "uint8arrays": "3.1.1", diff --git a/packages/issuer-rest/package.json b/packages/issuer-rest/package.json index f06fb058..5a141b03 100644 --- a/packages/issuer-rest/package.json +++ b/packages/issuer-rest/package.json @@ -15,7 +15,7 @@ "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", "@sphereon/ssi-express-support": "0.30.2-feature.mdoc.funke2.367", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", diff --git a/packages/issuer/package.json b/packages/issuer/package.json index 2b5b6934..3eae5336 100644 --- a/packages/issuer/package.json +++ b/packages/issuer/package.json @@ -12,7 +12,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "uuid": "^9.0.0" }, "peerDependencies": { diff --git a/packages/oid4vci-common/package.json b/packages/oid4vci-common/package.json index d7731797..1fd88ead 100644 --- a/packages/oid4vci-common/package.json +++ b/packages/oid4vci-common/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@sphereon/oid4vc-common": "workspace:*", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "cross-fetch": "^3.1.8", "debug": "^4.3.5", "jwt-decode": "^4.0.0", diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 9c317640..4ca497ba 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -20,7 +20,7 @@ "@sphereon/pex": "5.0.0-unstable.28", "dcql": "0.2.11", "@sphereon/pex-models": "^2.3.2", - "@sphereon/ssi-types": "link:../../SSI-SDK/packages/ssi-types", + "@sphereon/ssi-types": "0.32.0", "cross-fetch": "^4.0.0", "debug": "^4.3.5", "events": "^3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e6aadee..71d5d012 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: - '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types + '@sphereon/ssi-types': 0.32.0 dcql: 0.2.11 node-fetch: 2.6.12 @@ -77,8 +77,8 @@ importers: specifier: workspace:* version: link:../issuer '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 jose: specifier: ^4.10.0 version: 4.15.9 @@ -120,8 +120,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -205,8 +205,8 @@ importers: packages/common: dependencies: '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -273,8 +273,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -316,8 +316,8 @@ importers: specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -408,8 +408,8 @@ importers: specifier: workspace:* version: link:../common '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -457,8 +457,8 @@ importers: specifier: ^2.3.2 version: 2.3.2 '@sphereon/ssi-types': - specifier: link:../../../SSI-SDK/packages/ssi-types - version: link:../../../SSI-SDK/packages/ssi-types + specifier: 0.32.0 + version: 0.32.0 cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -2120,6 +2120,14 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@js-joda/core@5.6.3': + resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} + + '@js-joda/timezone@2.3.0': + resolution: {integrity: sha512-DHXdNs0SydSqC5f0oRJPpTcNfnpRojgBqMCFupQFv6WgeZAjU3DBx+A7JtaGPP3dHrP2Odi2N8Vf+uAm/8ynCQ==} + peerDependencies: + '@js-joda/core': '>=1.11.0' + '@lerna/create@8.1.9': resolution: {integrity: sha512-DPnl5lPX4v49eVxEbJnAizrpMdMTBz1qykZrAbBul9rfgk531v8oAt+Pm6O/rpAleRombNM7FJb5rYGzBJatOQ==} engines: {node: '>=18.0.0'} @@ -2536,6 +2544,10 @@ packages: react-native-securerandom: optional: true + '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': + resolution: {integrity: sha512-QXJ6R8ENiZV2rPMbn06cw5JKwqUYN1kzVRbYfONqE1PEXx1noQ4md7uxr2zSczi0ubKkNcbyYDNtIMTZIhGzmQ==} + bundledDependencies: [] + '@sphereon/pex-models@2.3.2': resolution: {integrity: sha512-foFxfLkRwcn/MOp/eht46Q7wsvpQGlO7aowowIIb5Tz9u97kYZ2kz6K2h2ODxWuv5CRA7Q0MY8XUBGE2lfOhOQ==} @@ -2560,6 +2572,9 @@ packages: '@sphereon/ssi-sdk-ext.key-utils@0.23.0': resolution: {integrity: sha512-BfULXvQmcUrBq2DqYxJHKnEoB2d5icu3TJ9GP2aP1WybSULTjL96Wv5r7QKgktcodKaL+F+oQ7r8sC9qBl1exw==} + '@sphereon/ssi-types@0.32.0': + resolution: {integrity: sha512-v5yC/bj1nvHE30cYMMqmjz2KHPpXj3OL8ZwnZQTiAMISS4DOVTjpYt0qZgb4eA1Lsdw2smd1bNYyVsOEJ02PAw==} + '@sphereon/wellknown-dids-client@0.1.3': resolution: {integrity: sha512-TAT24L3RoXD8ocrkTcsz7HuJmgjNjdoV6IXP1p3DdaI/GqkynytXE3J1+F7vUFMRYwY5nW2RaXSgDQhrFJemaA==} @@ -4759,6 +4774,9 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} + format-util@1.0.5: + resolution: {integrity: sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==} + formidable@2.1.2: resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==} @@ -11140,6 +11158,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@js-joda/core@5.6.3': {} + + '@js-joda/timezone@2.3.0(@js-joda/core@5.6.3)': + dependencies: + '@js-joda/core': 5.6.3 + '@lerna/create@8.1.9(encoding@0.1.13)(typescript@5.5.3)': dependencies: '@npmcli/arborist': 7.5.4 @@ -11864,6 +11888,12 @@ snapshots: expo: 48.0.21(@babel/core@7.26.0)(encoding@0.1.13) react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) + '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': + dependencies: + '@js-joda/core': 5.6.3 + '@js-joda/timezone': 2.3.0(@js-joda/core@5.6.3) + format-util: 1.0.5 + '@sphereon/pex-models@2.3.2': {} '@sphereon/pex@5.0.0-unstable.28': @@ -11873,12 +11903,14 @@ snapshots: '@sd-jwt/present': 0.7.2 '@sd-jwt/types': 0.7.2 '@sphereon/pex-models': 2.3.2 - '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types + '@sphereon/ssi-types': 0.32.0 ajv: 8.17.1 ajv-formats: 2.1.1(ajv@8.17.1) jwt-decode: 3.1.2 nanoid: 3.3.7 uint8arrays: 3.1.1 + transitivePeerDependencies: + - supports-color '@sphereon/ssi-express-support@0.30.2-feature.mdoc.funke2.367': dependencies: @@ -11923,13 +11955,25 @@ snapshots: - react-native-securerandom - supports-color + '@sphereon/ssi-types@0.32.0': + dependencies: + '@sd-jwt/decode': 0.7.2 + '@sphereon/kmp-mdoc-core': 0.2.0-SNAPSHOT.26 + debug: 4.3.7 + events: 3.3.0 + jwt-decode: 3.1.2 + uint8arrays: 3.1.1 + transitivePeerDependencies: + - supports-color + '@sphereon/wellknown-dids-client@0.1.3(encoding@0.1.13)': dependencies: - '@sphereon/ssi-types': link:../SSI-SDK/packages/ssi-types + '@sphereon/ssi-types': 0.32.0 cross-fetch: 3.1.8(encoding@0.1.13) jwt-decode: 3.1.2 transitivePeerDependencies: - encoding + - supports-color '@stablelib/aead@1.0.1': {} @@ -14938,6 +14982,8 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 + format-util@1.0.5: {} + formidable@2.1.2: dependencies: dezalgo: 1.0.4 From 47b9205caeb503bc90b4f4674c50a745324a17f4 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 11 Dec 2024 16:13:17 +0100 Subject: [PATCH 26/60] refactor: Removed packageManager from the package.json --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 3fb16fb7..bb28456b 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,5 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ], - "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" + ] } From fa3e1b892948ee9c272f880e806da17daacde077 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 17 Dec 2024 12:20:32 +0100 Subject: [PATCH 27/60] chore: lockfile --- pnpm-lock.yaml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71d5d012..f12956d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,9 +257,6 @@ importers: '@types/jest': specifier: ^29.5.12 version: 29.5.14 - '@types/jwt-decode': - specifier: ^3.1.0 - version: 3.1.0 typescript: specifier: 5.4.5 version: 5.4.5 @@ -547,9 +544,6 @@ importers: '@types/jest': specifier: ^29.5.11 version: 29.5.14 - '@types/jwt-decode': - specifier: ^3.1.0 - version: 3.1.0 '@types/language-tags': specifier: ^1.0.4 version: 1.0.4 @@ -2857,10 +2851,6 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/jwt-decode@3.1.0': - resolution: {integrity: sha512-tthwik7TKkou3mVnBnvVuHnHElbjtdbM63pdBCbZTirCt3WAdM73Y79mOri7+ljsS99ZVwUFZHLMxJuJnv/z1w==} - deprecated: This is a stub types definition. jwt-decode provides its own type definitions, so you do not need this installed. - '@types/language-tags@1.0.4': resolution: {integrity: sha512-20PQbifv3v/djCT+KlXybv0KqO5ofoR1qD1wkinN59kfggTPVTWGmPFgL/1yWuDyRcsQP/POvkqK+fnl5nOwTg==} @@ -12399,10 +12389,6 @@ snapshots: '@types/json5@0.0.29': {} - '@types/jwt-decode@3.1.0': - dependencies: - jwt-decode: 4.0.0 - '@types/language-tags@1.0.4': {} '@types/mime@1.3.5': {} From 9b7a2c394b7b592bc2c563e112d7f2ed3a7d6c94 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 17 Dec 2024 13:43:13 +0100 Subject: [PATCH 28/60] chore: use DcqlQuery object just like presentation_definition has an object --- package.json | 2 +- packages/callback-example/package.json | 2 +- packages/client/package.json | 2 +- packages/common/package.json | 2 +- packages/issuer-rest/package.json | 2 +- packages/issuer/package.json | 2 +- packages/oid4vci-common/package.json | 2 +- packages/siop-oid4vp/lib/rp/RPBuilder.ts | 60 +++++++++++--------- packages/siop-oid4vp/lib/types/SIOP.types.ts | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 49 ++++++++-------- 11 files changed, 66 insertions(+), 61 deletions(-) diff --git a/package.json b/package.json index bb28456b..e1482a95 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node": ">=18" }, "resolutions": { - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "dcql": "0.2.11", "node-fetch": "2.6.12" }, diff --git a/packages/callback-example/package.json b/packages/callback-example/package.json index 2b771138..bb1dd3e1 100644 --- a/packages/callback-example/package.json +++ b/packages/callback-example/package.json @@ -19,7 +19,7 @@ "@sphereon/oid4vci-client": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "jose": "^4.10.0" }, "devDependencies": { diff --git a/packages/client/package.json b/packages/client/package.json index 9617ba91..5e7acb8a 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,7 +17,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "cross-fetch": "^3.1.8", "debug": "^4.3.5" }, diff --git a/packages/common/package.json b/packages/common/package.json index e7a0f0d8..04ea2a3d 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -10,7 +10,7 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "jwt-decode": "^4.0.0", "sha.js": "^2.4.11", "uint8arrays": "3.1.1", diff --git a/packages/issuer-rest/package.json b/packages/issuer-rest/package.json index 5a141b03..5c3007e0 100644 --- a/packages/issuer-rest/package.json +++ b/packages/issuer-rest/package.json @@ -15,7 +15,7 @@ "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", "@sphereon/ssi-express-support": "0.30.2-feature.mdoc.funke2.367", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", diff --git a/packages/issuer/package.json b/packages/issuer/package.json index 3eae5336..ea3d1f4f 100644 --- a/packages/issuer/package.json +++ b/packages/issuer/package.json @@ -12,7 +12,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "uuid": "^9.0.0" }, "peerDependencies": { diff --git a/packages/oid4vci-common/package.json b/packages/oid4vci-common/package.json index 1fd88ead..ffcfdb85 100644 --- a/packages/oid4vci-common/package.json +++ b/packages/oid4vci-common/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@sphereon/oid4vc-common": "workspace:*", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "cross-fetch": "^3.1.8", "debug": "^4.3.5", "jwt-decode": "^4.0.0", diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index 6a321c3e..da222746 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -23,6 +23,7 @@ import { import { assignIfAuth, assignIfRequestObject, isTarget, isTargetOrNoTargets } from './Opts' import { RP } from './RP' import { IRPSessionManager } from './types' +import { DcqlQuery } from 'dcql' export class RPBuilder { requestObjectBy: ObjectBy @@ -226,73 +227,78 @@ export class RPBuilder { return this } - withDcqlQuery(dcqlQuery: string, targets?: PropertyTargets): RPBuilder { - this._authorizationRequestPayload.dcql_query = assignIfAuth( - { - propertyValue: dcqlQuery, - targets, - }, - false, - ) - this._requestObjectPayload.dcql_query = assignIfRequestObject( - { - propertyValue: dcqlQuery, - targets, - }, - true, - ) + withDcqlQuery(dcqlQuery: DcqlQuery, targets?: PropertyTargets): RPBuilder { + if (this.getSupportedRequestVersion() >= SupportedVersion.SIOPv2_D12_OID4VP_D20) { + this._authorizationRequestPayload.dcql_query = assignIfAuth( + { + propertyValue: dcqlQuery, + targets + }, + false + ) + this._requestObjectPayload.dcql_query = assignIfRequestObject( + { + propertyValue: dcqlQuery, + targets + }, + true + ) + } return this } - withPresentationDefinition(definitionOpts: { definition: IPresentationDefinition; definitionUri?: string }, targets?: PropertyTargets): RPBuilder { + withPresentationDefinition(definitionOpts: { + definition: IPresentationDefinition; + definitionUri?: string + }, targets?: PropertyTargets): RPBuilder { const { definition, definitionUri } = definitionOpts if (this.getSupportedRequestVersion() < SupportedVersion.SIOPv2_D11) { const definitionProperties = { presentation_definition: definition, - presentation_definition_uri: definitionUri, + presentation_definition_uri: definitionUri } const vp_token = { ...definitionProperties } if (isTarget(PropertyTarget.AUTHORIZATION_REQUEST, targets)) { this._authorizationRequestPayload.claims = { ...(this._authorizationRequestPayload.claims ? this._authorizationRequestPayload.claims : {}), - vp_token: vp_token, + vp_token: vp_token } } if (isTargetOrNoTargets(PropertyTarget.REQUEST_OBJECT, targets)) { this._requestObjectPayload.claims = { ...(this._requestObjectPayload.claims ? this._requestObjectPayload.claims : {}), - vp_token: vp_token, + vp_token: vp_token } } } else { this._authorizationRequestPayload.presentation_definition = assignIfAuth( { propertyValue: definition, - targets, + targets }, - false, + false ) this._authorizationRequestPayload.presentation_definition_uri = assignIfAuth( { propertyValue: definitionUri, - targets, + targets }, - true, + true ) this._requestObjectPayload.presentation_definition = assignIfRequestObject( { propertyValue: definition, - targets, + targets }, - true, + true ) this._requestObjectPayload.presentation_definition_uri = assignIfRequestObject( { propertyValue: definitionUri, - targets, + targets }, - true, + true ) } return this diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 28705d5b..24622244 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -100,7 +100,7 @@ export interface AuthorizationRequestPayloadVD12OID4VPD20 presentation_definition_uri?: string client_id_scheme?: ClientIdSchemeOID4VPD20 response_uri?: string // New since OID4VP18 OPTIONAL. The Response URI to which the Wallet MUST send the Authorization Response using an HTTPS POST request as defined by the Response Mode direct_post. The Response URI receives all Authorization Response parameters as defined by the respective Response Type. When the response_uri parameter is present, the redirect_uri Authorization Request parameter MUST NOT be present. If the redirect_uri Authorization Request parameter is present when the Response Mode is direct_post, the Wallet MUST return an invalid_request Authorization Response error. - dcql_query?: string + dcql_query?: DcqlQuery } export type ClientIdSchemeOID4VPD18 = 'pre-registered' | 'redirect_uri' | 'entity_id' | 'did' diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 4e9ac139..2e98f766 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -20,7 +20,7 @@ "@sphereon/pex": "5.0.0-unstable.28", "dcql": "0.2.11", "@sphereon/pex-models": "^2.3.2", - "@sphereon/ssi-types": "0.32.0", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", "cross-fetch": "^4.0.0", "debug": "^4.3.5", "events": "^3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f12956d5..73d98481 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: - '@sphereon/ssi-types': 0.32.0 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 dcql: 0.2.11 node-fetch: 2.6.12 @@ -77,8 +77,8 @@ importers: specifier: workspace:* version: link:../issuer '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 jose: specifier: ^4.10.0 version: 4.15.9 @@ -120,8 +120,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -205,8 +205,8 @@ importers: packages/common: dependencies: '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -270,8 +270,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -313,8 +313,8 @@ importers: specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -405,8 +405,8 @@ importers: specifier: workspace:* version: link:../common '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -454,8 +454,8 @@ importers: specifier: ^2.3.2 version: 2.3.2 '@sphereon/ssi-types': - specifier: 0.32.0 - version: 0.32.0 + specifier: 0.32.1-feature.VDX.341.27 + version: 0.32.1-feature.VDX.341.27 cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -2540,7 +2540,6 @@ packages: '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': resolution: {integrity: sha512-QXJ6R8ENiZV2rPMbn06cw5JKwqUYN1kzVRbYfONqE1PEXx1noQ4md7uxr2zSczi0ubKkNcbyYDNtIMTZIhGzmQ==} - bundledDependencies: [] '@sphereon/pex-models@2.3.2': resolution: {integrity: sha512-foFxfLkRwcn/MOp/eht46Q7wsvpQGlO7aowowIIb5Tz9u97kYZ2kz6K2h2ODxWuv5CRA7Q0MY8XUBGE2lfOhOQ==} @@ -2566,8 +2565,8 @@ packages: '@sphereon/ssi-sdk-ext.key-utils@0.23.0': resolution: {integrity: sha512-BfULXvQmcUrBq2DqYxJHKnEoB2d5icu3TJ9GP2aP1WybSULTjL96Wv5r7QKgktcodKaL+F+oQ7r8sC9qBl1exw==} - '@sphereon/ssi-types@0.32.0': - resolution: {integrity: sha512-v5yC/bj1nvHE30cYMMqmjz2KHPpXj3OL8ZwnZQTiAMISS4DOVTjpYt0qZgb4eA1Lsdw2smd1bNYyVsOEJ02PAw==} + '@sphereon/ssi-types@0.32.1-feature.VDX.341.27': + resolution: {integrity: sha512-Mw72f13IckggZmQ2uXlcq/gHgwoV+Mqtj3/SyBHZrxkvAq9LpWynImrlgiQDkBGlvpQ3chZ/ju8pQIPDTIqFWA==} '@sphereon/wellknown-dids-client@0.1.3': resolution: {integrity: sha512-TAT24L3RoXD8ocrkTcsz7HuJmgjNjdoV6IXP1p3DdaI/GqkynytXE3J1+F7vUFMRYwY5nW2RaXSgDQhrFJemaA==} @@ -10027,7 +10026,7 @@ snapshots: '@digitalcredentials/bnid@2.1.2(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1))': dependencies: '@digitalcredentials/base58-universal': 1.0.1 - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) yargs: 15.4.1 transitivePeerDependencies: - react-native @@ -11876,7 +11875,7 @@ snapshots: webcrypto-shim: 0.1.7 optionalDependencies: expo: 48.0.21(@babel/core@7.26.0)(encoding@0.1.13) - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': dependencies: @@ -11893,7 +11892,7 @@ snapshots: '@sd-jwt/present': 0.7.2 '@sd-jwt/types': 0.7.2 '@sphereon/pex-models': 2.3.2 - '@sphereon/ssi-types': 0.32.0 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 ajv: 8.17.1 ajv-formats: 2.1.1(ajv@8.17.1) jwt-decode: 3.1.2 @@ -11945,20 +11944,20 @@ snapshots: - react-native-securerandom - supports-color - '@sphereon/ssi-types@0.32.0': + '@sphereon/ssi-types@0.32.1-feature.VDX.341.27': dependencies: '@sd-jwt/decode': 0.7.2 '@sphereon/kmp-mdoc-core': 0.2.0-SNAPSHOT.26 debug: 4.3.7 events: 3.3.0 - jwt-decode: 3.1.2 + jwt-decode: 4.0.0 uint8arrays: 3.1.1 transitivePeerDependencies: - supports-color '@sphereon/wellknown-dids-client@0.1.3(encoding@0.1.13)': dependencies: - '@sphereon/ssi-types': 0.32.0 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 cross-fetch: 3.1.8(encoding@0.1.13) jwt-decode: 3.1.2 transitivePeerDependencies: @@ -18214,7 +18213,7 @@ snapshots: react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) optional: true - react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)): + react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)): dependencies: base64-js: 1.5.1 react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) From 9b4bb1f5263fba2a9cc0acf80811b37bca764670 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 17 Dec 2024 16:21:53 +0100 Subject: [PATCH 29/60] chore: only show DcqlQuery when present --- packages/siop-oid4vp/lib/rp/RP.ts | 8 ++++++-- packages/siop-oid4vp/lib/rp/RPBuilder.ts | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index 827db4c4..52981b78 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -424,8 +424,12 @@ export class RP { state, nonce, verification: mergeVerificationOpts(this._verifyResponseOptions, opts), - presentationDefinitions: opts?.presentationDefinitions ?? this._verifyResponseOptions.presentationDefinitions, - dcqlQuery: opts?.dcqlQuery ?? this._verifyResponseOptions.dcqlQuery, + ...(opts?.presentationDefinitions && !opts?.dcqlQuery && { + presentationDefinitions: this._verifyResponseOptions.presentationDefinitions + }), + ...(opts?.dcqlQuery && { + dcqlQuery: this._verifyResponseOptions.dcqlQuery + }) } } diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index 6a321c3e..4e3c5f6c 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -241,10 +241,16 @@ export class RPBuilder { }, true, ) + this._authorizationRequestPayload.presentation_definition = undefined + this._requestObjectPayload.presentation_definition = undefined return this } withPresentationDefinition(definitionOpts: { definition: IPresentationDefinition; definitionUri?: string }, targets?: PropertyTargets): RPBuilder { + if(this._authorizationRequestPayload.dcql_query) { + return this + } + const { definition, definitionUri } = definitionOpts if (this.getSupportedRequestVersion() < SupportedVersion.SIOPv2_D11) { From 1020b5bb28fefcf4b3537d91fce4f8742d0a2ad5 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 17 Dec 2024 19:17:13 +0100 Subject: [PATCH 30/60] test: Added AuthenticationRequest and AuthenticationResponse queries --- .../AuthenticationRequest.request.spec.ts | 82 ++++++++++ .../AuthenticationResponse.response.spec.ts | 152 ++++++++++++++++++ 2 files changed, 234 insertions(+) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationRequest.request.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationRequest.request.spec.ts index 12e487b8..3b12ff26 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationRequest.request.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationRequest.request.spec.ts @@ -26,6 +26,7 @@ import { VERIFIERZ_PURPOSE_TO_VERIFY, VERIFIERZ_PURPOSE_TO_VERIFY_NL, } from './data/mockedData' +import { DcqlQuery } from 'dcql' const EXAMPLE_REDIRECT_URL = 'https://acme.com/hello' const EXAMPLE_REFERENCE_URL = 'https://rp.acme.com/siop/jwts' @@ -671,4 +672,85 @@ describe('create Request JWT should', () => { } await expect(URI.fromOpts(opts)).rejects.toThrow(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) }) + + it('should succeed when requesting with a valid dcql query', async () => { + const dcqlQuery: DcqlQuery = { + credentials: [ + { + id: 'Credentials', + format: 'jwt_vc_json', + claims: [ + { + id: 'ID Card Credential', + path: ['$.issuer.id'], + values: ['did:example:issuer'], + }, + ], + }, + ], + } + const opts: CreateAuthorizationRequestOpts = { + version: SupportedVersion.SIOPv2_ID1, + payload: { + client_id: WELL_KNOWN_OPENID_FEDERATION, + scope: 'test', + response_type: 'vp_token', + request_object_signing_alg_values_supported: [SigningAlgo.ES256, SigningAlgo.EDDSA], + redirect_uri: EXAMPLE_REDIRECT_URL, + }, + requestObject: { + jwtIssuer: { method: 'did', didUrl: KID, alg: SigningAlgo.ES256K }, + passBy: PassBy.REFERENCE, + reference_uri: EXAMPLE_REFERENCE_URL, + + createJwtCallback: getCreateJwtCallback({ + hexPrivateKey: HEX_KEY, + did: DID, + kid: KID, + alg: SigningAlgo.ES256K, + }), + payload: { + client_id: WELL_KNOWN_OPENID_FEDERATION, + scope: 'test', + response_type: 'vp_token', + redirect_uri: EXAMPLE_REDIRECT_URL, + request_object_signing_alg_values_supported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + claims: { + vp_token: { + dcql_query: JSON.stringify(dcqlQuery) + }, + }, + }, + }, + clientMetadata: { + client_id: WELL_KNOWN_OPENID_FEDERATION, + idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + responseTypesSupported: [ResponseType.ID_TOKEN], + scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], + subject_syntax_types_supported: ['did:ethr:', SubjectIdentifierType.DID], + subjectTypesSupported: [SubjectType.PAIRWISE], + vpFormatsSupported: { + ldp_vc: { + proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019], + }, + }, + + passBy: PassBy.VALUE, + + logo_uri: VERIFIER_LOGO_FOR_CLIENT, + clientName: VERIFIER_NAME_FOR_CLIENT, + 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100305', + clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, + 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, + }, + } + + const uriRequest = await URI.fromOpts(opts) + + const uriDecoded = decodeURIComponent(uriRequest.encodedUri) + expect(uriDecoded.startsWith('openid4vp://?')).toBeTruthy() + expect(uriDecoded).toContain(`request_uri=https://rp.acme.com/siop/jwts`) + expect((await (await uriRequest.toAuthorizationRequest())?.requestObject?.getPayload())?.claims.vp_token).toBeDefined() + }) }) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index 779480d3..b6908aad 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -8,6 +8,13 @@ import { IVerifiablePresentation, OriginalVerifiableCredential, } from '@sphereon/ssi-types' +import { + DcqlCredentialRepresentation, + DcqlPresentationRecord, + DcqlQuery, + DcqlQueryResult +} from 'dcql' +import { Json } from 'dcql/dist/src/u-dcql' import { AuthorizationResponse, @@ -650,4 +657,149 @@ describe('create JWT from Request JWT should', () => { const authResponse = AuthorizationResponse.fromRequestObject(jwt, responseOpts, verifyOpts) await expect(authResponse).toBeDefined() }) + + it('succeed when valid JWT with DCQL query is passed in', async () => { + expect.assertions(1) + + const mockReqEntity = await mockedGetEnterpriseAuthToken('REQ COMPANY') + const mockResEntity = await mockedGetEnterpriseAuthToken('RES COMPANY') + + const dcqlQuery: DcqlQuery = { + credentials: [ + { + id: 'Credentials', + format: 'jwt_vc_json-ld', + claims: [ + { + id: 'ID_Card_Credential', + path: ['$.issuer.id'], + values: ['did:example:issuer'], + }, + ], + }, + ], + } + + const dcqlParsedQuery = DcqlQuery.parse(dcqlQuery) + DcqlQuery.validate(dcqlParsedQuery) + + const requestOpts: CreateAuthorizationRequestOpts = { + version: SupportedVersion.SIOPv2_ID1, + requestObject: { + passBy: PassBy.REFERENCE, + reference_uri: 'https://my-request.com/here', + jwtIssuer: { method: 'did', didUrl: mockReqEntity.did, alg: SigningAlgo.ES256K }, + createJwtCallback: getCreateJwtCallback({ + hexPrivateKey: mockReqEntity.hexPrivateKey, + did: mockReqEntity.did, + kid: `${mockReqEntity.did}#controller`, + alg: SigningAlgo.ES256K, + }), + payload: { + client_id: WELL_KNOWN_OPENID_FEDERATION, + scope: 'test', + response_type: 'id_token vp_token', + redirect_uri: EXAMPLE_REDIRECT_URL, + claims: { + vp_token: { + dcql_query: dcqlParsedQuery, + }, + }, + }, + }, + clientMetadata: { + client_id: WELL_KNOWN_OPENID_FEDERATION, + idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + subject_syntax_types_supported: ['did:ethr:', SubjectIdentifierType.DID], + requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + responseTypesSupported: [ResponseType.ID_TOKEN], + scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], + subjectTypesSupported: [SubjectType.PAIRWISE], + vpFormatsSupported: { + ldp_vc: { + proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019], + }, + }, + passBy: PassBy.VALUE, + logo_uri: VERIFIER_LOGO_FOR_CLIENT, + clientName: VERIFIER_NAME_FOR_CLIENT, + 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100315', + clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, + 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, + }, + } + + const vc: DcqlCredentialRepresentation = { + docType: 'jsonld', + claims: { + id: 'https://example.com/credentials/1872', + type: ['VerifiableCredential', 'IDCardCredential'], + '@context': ['https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/2018/credentials/examples/v1/IDCardCredential'], + issuer: { + id: 'did:example:issuer', + }, + issuanceDate: '2010-01-01T19:23:24Z', + credentialSubject: { + given_name: 'Fredrik', + family_name: 'Stremberg', + birthdate: '1949-01-22', + }, + }, + } + + const dcqlQueryResult: DcqlQueryResult = DcqlQuery.query(dcqlQuery, [vc]) + + const presentation: DcqlPresentationRecord.Output = {} + for (const [key, value] of Object.entries(dcqlQueryResult.credential_matches)) { + if (value.success) { + presentation[key] = value.output as string | { [x: string]: Json } + } + } + + const encodedPresentationRecord = DcqlPresentationRecord.parse(presentation) + + const responseOpts: AuthorizationResponseOpts = { + responseURI: EXAMPLE_REDIRECT_URL, + responseURIType: 'redirect_uri', + registration: { + authorizationEndpoint: 'www.myauthorizationendpoint.com', + issuer: ResponseIss.SELF_ISSUED_V2, + responseTypesSupported: [ResponseType.ID_TOKEN], + passBy: PassBy.REFERENCE, + reference_uri: EXAMPLE_REFERENCE_URL, + + subject_syntax_types_supported: ['did:ethr:', SubjectIdentifierType.DID], + vpFormats: { + ldp_vc: { + proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019], + }, + }, + logo_uri: VERIFIER_LOGO_FOR_CLIENT, + clientName: VERIFIER_NAME_FOR_CLIENT, + 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100316', + clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, + 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, + }, + createJwtCallback: getCreateJwtCallback({ + did: mockResEntity.did, + hexPrivateKey: mockResEntity.hexPrivateKey, + kid: `${mockResEntity.did}#controller`, + alg: SigningAlgo.ES256K, + }), + jwtIssuer: { method: 'did', didUrl: `${mockResEntity.did}#controller`, alg: SigningAlgo.ES256K }, + dcqlQuery: { + encodedPresentationRecord + }, + responseMode: ResponseMode.POST, + } + + const requestObject = await RequestObject.fromOpts(requestOpts) + /* console.log( + JSON.stringify(await AuthenticationResponse.createJWTFromRequestJWT(requestWithJWT.jwt, responseOpts, verifyOpts)) + );*/ + const jwt = await requestObject.toJwt() + if (!jwt) throw new Error('JWT is undefined') + const authorizationRequest = await AuthorizationResponse.fromRequestObject(jwt, responseOpts, verifyOpts) + expect(authorizationRequest).toBeDefined() + }) }) From f94344e427494c9c50c7183c7de0c420ac19cc81 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Wed, 18 Dec 2024 15:06:32 +0100 Subject: [PATCH 31/60] chore: "fixed succeed when valid JWT with DCQL query is passed in" to pass in a SIOPv2_D12_OID4VP_D20 version request --- .../AuthenticationResponse.response.spec.ts | 29 ++----------------- packages/siop-oid4vp/lib/id-token/IDToken.ts | 2 +- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index b6908aad..dea1906d 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -684,7 +684,7 @@ describe('create JWT from Request JWT should', () => { DcqlQuery.validate(dcqlParsedQuery) const requestOpts: CreateAuthorizationRequestOpts = { - version: SupportedVersion.SIOPv2_ID1, + version: SupportedVersion.SIOPv2_D12_OID4VP_D20, requestObject: { passBy: PassBy.REFERENCE, reference_uri: 'https://my-request.com/here', @@ -700,11 +700,7 @@ describe('create JWT from Request JWT should', () => { scope: 'test', response_type: 'id_token vp_token', redirect_uri: EXAMPLE_REDIRECT_URL, - claims: { - vp_token: { - dcql_query: dcqlParsedQuery, - }, - }, + dcql_query: JSON.stringify(dcqlParsedQuery), }, }, clientMetadata: { @@ -761,25 +757,6 @@ describe('create JWT from Request JWT should', () => { const responseOpts: AuthorizationResponseOpts = { responseURI: EXAMPLE_REDIRECT_URL, responseURIType: 'redirect_uri', - registration: { - authorizationEndpoint: 'www.myauthorizationendpoint.com', - issuer: ResponseIss.SELF_ISSUED_V2, - responseTypesSupported: [ResponseType.ID_TOKEN], - passBy: PassBy.REFERENCE, - reference_uri: EXAMPLE_REFERENCE_URL, - - subject_syntax_types_supported: ['did:ethr:', SubjectIdentifierType.DID], - vpFormats: { - ldp_vc: { - proof_type: [IProofType.EcdsaSecp256k1Signature2019, IProofType.EcdsaSecp256k1Signature2019], - }, - }, - logo_uri: VERIFIER_LOGO_FOR_CLIENT, - clientName: VERIFIER_NAME_FOR_CLIENT, - 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100316', - clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, - 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, - }, createJwtCallback: getCreateJwtCallback({ did: mockResEntity.did, hexPrivateKey: mockResEntity.hexPrivateKey, @@ -790,7 +767,7 @@ describe('create JWT from Request JWT should', () => { dcqlQuery: { encodedPresentationRecord }, - responseMode: ResponseMode.POST, + responseMode: ResponseMode.DIRECT_POST, } const requestObject = await RequestObject.fromOpts(requestOpts) diff --git a/packages/siop-oid4vp/lib/id-token/IDToken.ts b/packages/siop-oid4vp/lib/id-token/IDToken.ts index ac142218..d94d36bb 100644 --- a/packages/siop-oid4vp/lib/id-token/IDToken.ts +++ b/packages/siop-oid4vp/lib/id-token/IDToken.ts @@ -99,7 +99,7 @@ export class IDToken { const did = jwtIssuer.didUrl.split('#')[0] this._payload.sub = did - const issuer = this._responseOpts.registration.issuer || this._payload.iss + const issuer = this._responseOpts.registration?.issuer || this._payload.iss if (!issuer || !(issuer.includes(ResponseIss.SELF_ISSUED_V2) || issuer === this._payload.sub)) { throw new Error(SIOPErrors.NO_SELF_ISSUED_ISS) } From 7e0c198c38f611760ea272ec498eb1163965f922 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 18 Dec 2024 17:47:52 +0100 Subject: [PATCH 32/60] Fix: Added the hasher and compact sdjwt credential to the AuthorizationRequest --- .../AuthenticationResponse.response.spec.ts | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index dea1906d..a82a730e 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -8,13 +8,7 @@ import { IVerifiablePresentation, OriginalVerifiableCredential, } from '@sphereon/ssi-types' -import { - DcqlCredentialRepresentation, - DcqlPresentationRecord, - DcqlQuery, - DcqlQueryResult -} from 'dcql' -import { Json } from 'dcql/dist/src/u-dcql' +import { DcqlCredentialRepresentation, DcqlPresentationRecord, DcqlQuery, DcqlQueryResult } from 'dcql' import { AuthorizationResponse, @@ -39,7 +33,7 @@ import SIOPErrors from '../types/Errors' import { getCreateJwtCallback, getVerifyJwtCallback } from './DidJwtTestUtils' import { getResolver } from './ResolverTestUtils' -import { mockedGetEnterpriseAuthToken, WELL_KNOWN_OPENID_FEDERATION } from './TestUtils' +import { mockedGetEnterpriseAuthToken, pexHasher, WELL_KNOWN_OPENID_FEDERATION } from './TestUtils' import { UNIT_TEST_TIMEOUT, VERIFIER_LOGO_FOR_CLIENT, @@ -97,6 +91,7 @@ describe('create JWT from Request JWT should', () => { const resolver = getResolver('ethr') const verifyOpts: VerifyAuthorizationRequestOpts = { + hasher: pexHasher, verifyJwtCallback: getVerifyJwtCallback(resolver), verification: {}, supportedVersions: [SupportedVersion.SIOPv2_ID1], @@ -668,12 +663,11 @@ describe('create JWT from Request JWT should', () => { credentials: [ { id: 'Credentials', - format: 'jwt_vc_json-ld', + format: 'vc+sd-jwt', claims: [ { - id: 'ID_Card_Credential', - path: ['$.issuer.id'], - values: ['did:example:issuer'], + path: ['given_name'], + values: ['John'], }, ], }, @@ -725,30 +719,47 @@ describe('create JWT from Request JWT should', () => { }, } - const vc: DcqlCredentialRepresentation = { - docType: 'jsonld', - claims: { - id: 'https://example.com/credentials/1872', - type: ['VerifiableCredential', 'IDCardCredential'], - '@context': ['https://www.w3.org/2018/credentials/v1', 'https://www.w3.org/2018/credentials/examples/v1/IDCardCredential'], - issuer: { - id: 'did:example:issuer', + const sdjwt = { + compactJwtVc: + 'eyJ0eXAiOiJ2YytzZC1qd3QiLCJraWQiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOaUlzSW5WelpTSTZJbk5wWnlJc0ltdDBlU0k2SWtWRElpd2lZM0oySWpvaVVDMHlOVFlpTENKNElqb2lTMGRwYzNodlUzaDJhVzB4YTFOSU1XSnROMnhmUkhCeVIyczNZa2RrWkVaYVdXWnRjVXB1VjJWb1NTSXNJbmtpT2lKYVEzQldUVVZSTkhsNGNUSlZiVGRDVGpoSVQyNUdlamszTTFBMFVUQlVkbmRuZVhWUlgyRmlURlZWSW4wIzAiLCJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOaUlzSW5WelpTSTZJbk5wWnlJc0ltdDBlU0k2SWtWRElpd2lZM0oySWpvaVVDMHlOVFlpTENKNElqb2lXRkpXUVhsNVJIQldNbXBNTm5oNlUwSktZM1JIZW0xS1pqbFFlV0Z4WHpNdFRVeHJlR0ZoUlRBNFRTSXNJbmtpT2lKQ1NtOUtWM05WYTBaQlUyVlRZMmx4VDFsNVNWTTBZMFpoZVU4emFHaEJTalZaYjJ0dU9IcFRTVEZuSW4wIzAiLCJpc3MiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlV6STFOaUlzSW5WelpTSTZJbk5wWnlJc0ltdDBlU0k2SWtWRElpd2lZM0oySWpvaVVDMHlOVFlpTENKNElqb2lTMGRwYzNodlUzaDJhVzB4YTFOSU1XSnROMnhmUkhCeVIyczNZa2RrWkVaYVdXWnRjVXB1VjJWb1NTSXNJbmtpT2lKYVEzQldUVVZSTkhsNGNUSlZiVGRDVGpoSVQyNUdlamszTTFBMFVUQlVkbmRuZVhWUlgyRmlURlZWSW4wIzAiLCJpYXQiOjE3MzQ0NTgwNDIsInZjdCI6InVybjpldS5ldXJvcGEuZWMuZXVkaTpwaWQ6MSIsIl9zZCI6WyIwWWdpR25hck1LSERnVWx1QktteGdRZUJ4OF8xazMwd3NSRVN1X2t1Y0JFIiwiNEpwU2JzUEsxZndUQzRhR24zZ0hXb1BkVEJrMExOTWZMOEJXeEIxZ1JPWSIsIjRpZmplQUZveUEyQmc0STVNWEFrMVlyc1AtUVBQQXRnZGlHY0RMQTZiTFEiLCJBdTFjdURISUNISE1jUjZxM2R3d1pHbHp5dzMwSXhvTGVhWlNxRktEbmo4IiwiQ0QxbWxOY19VaVBoQUp6YkJveTVMY3dtekFNZTM3d0VLZF9iMTB6QTNxNCIsInFwZ1FOUVRac0VJWHdxUk9fT24xdUVCSVVNODBTcTJLR2tlN0JSU2N0WHciXSwiX3NkX2FsZyI6IlNIQS0yNTYifQ.P84d0CoS4M-zQ29l3S97RMatfJMYkoTgR5EqSMTdYlZAMp4e8iiuz2PXQMfJ-_undCvg4SRXxDACGiLL3Tt7Bw~WyJlNTFiNWI2NS0wNzM3LTQ0MjQtYTUxYS1jNGYzZGNlZGFmMmYiLCJnaXZlbl9uYW1lIiwiSm9obiJd~WyIxM2I1NDIwNi1kYWQ3LTQ3N2UtODYyZC03N2ZiMTQ1MDE5NjUiLCJmYW1pbHlfbmFtZSIsIkRvZSJd~WyJkMmQxNjg3Zi04ZmY4LTRlOTMtYWJjYi1hYTNlNGVjYzY0ZTMiLCJlbWFpbCIsImpvaG5kZW9AZXhhbXBsZS5jb20iXQ~WyIyZDA4YTk2YS03YzYwLTQ3NDEtYTI5YS00ZjBjYTFlNGQ3M2IiLCJwaG9uZSIsIisxLTIwMi01NTUtMDEwMSJd~WyI2YjVkN2FmOS01ZmIxLTQzNTEtYWM1ZS1hMzA1YTBkNjU0ZDUiLCJhZGRyZXNzIix7InN0cmVldF9hZGRyZXNzIjoiMTIzIE1haW4gU3QiLCJsb2NhbGl0eSI6IkFueXRvd24iLCJyZWdpb24iOiJBbnlzdGF0ZSIsImNvdW50cnkiOiJVUyJ9XQ~WyI5MmYzY2M5ZC0yMjQ2LTRiODQtYTk5OS0xYmQyM2U0OGQ0MGEiLCJiaXJ0aGRhdGUiLCIxOTQwLTAxLTAxIl0~', + decodedPayload: { + header: { + typ: 'vc+sd-jwt', + kid: 'did:jwk:eyJhbGciOiJFUzI1NiIsInVzZSI6InNpZyIsImt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiS0dpc3hvU3h2aW0xa1NIMWJtN2xfRHByR2s3YkdkZEZaWWZtcUpuV2VoSSIsInkiOiJaQ3BWTUVRNHl4cTJVbTdCTjhIT25Gejk3M1A0UTBUdndneXVRX2FiTFVVIn0#0', + alg: 'ES256', }, - issuanceDate: '2010-01-01T19:23:24Z', - credentialSubject: { - given_name: 'Fredrik', - family_name: 'Stremberg', - birthdate: '1949-01-22', + payload: { + sub: 'did:jwk:eyJhbGciOiJFUzI1NiIsInVzZSI6InNpZyIsImt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiWFJWQXl5RHBWMmpMNnh6U0JKY3RHem1KZjlQeWFxXzMtTUxreGFhRTA4TSIsInkiOiJCSm9KV3NVa0ZBU2VTY2lxT1l5SVM0Y0ZheU8zaGhBSjVZb2tuOHpTSTFnIn0#0', + iss: 'did:jwk:eyJhbGciOiJFUzI1NiIsInVzZSI6InNpZyIsImt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiS0dpc3hvU3h2aW0xa1NIMWJtN2xfRHByR2s3YkdkZEZaWWZtcUpuV2VoSSIsInkiOiJaQ3BWTUVRNHl4cTJVbTdCTjhIT25Gejk3M1A0UTBUdndneXVRX2FiTFVVIn0#0', + iat: 1734458042, + vct: 'urn:eu.europa.ec.eudi:pid:1', + given_name: 'John', + email: 'johndeo@example.com', + birthdate: '1940-01-01', + phone: '+1-202-555-0101', + address: { + street_address: '123 Main St', + locality: 'Anytown', + region: 'Anystate', + country: 'US', + }, + family_name: 'Doe', }, + kb: undefined, }, } + const vc: DcqlCredentialRepresentation = { + vct: sdjwt.decodedPayload.payload.vct, + claims: sdjwt.decodedPayload.payload, + } + const dcqlQueryResult: DcqlQueryResult = DcqlQuery.query(dcqlQuery, [vc]) const presentation: DcqlPresentationRecord.Output = {} for (const [key, value] of Object.entries(dcqlQueryResult.credential_matches)) { if (value.success) { - presentation[key] = value.output as string | { [x: string]: Json } + presentation[key] = sdjwt.compactJwtVc } } @@ -765,7 +776,7 @@ describe('create JWT from Request JWT should', () => { }), jwtIssuer: { method: 'did', didUrl: `${mockResEntity.did}#controller`, alg: SigningAlgo.ES256K }, dcqlQuery: { - encodedPresentationRecord + encodedPresentationRecord, }, responseMode: ResponseMode.DIRECT_POST, } From 169118cd8b87bf784714e2639f208b38b1a4767c Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 30 Dec 2024 13:50:11 +0100 Subject: [PATCH 33/60] Fix: Fixed broken IT tests --- packages/siop-oid4vp/lib/__tests__/IT.spec.ts | 4 ++-- packages/siop-oid4vp/lib/rp/RP.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/IT.spec.ts b/packages/siop-oid4vp/lib/__tests__/IT.spec.ts index 11ff6795..8bb15898 100644 --- a/packages/siop-oid4vp/lib/__tests__/IT.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/IT.spec.ts @@ -141,7 +141,7 @@ function getVCs(): IVerifiableCredential[] { return vcs } -describe.skip('RP and OP interaction should', () => { +describe('RP and OP interaction should', () => { // FIXME SDK-45 Uniresolver failing it( 'succeed when calling each other in the full flow', @@ -425,7 +425,7 @@ describe.skip('RP and OP interaction should', () => { const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) await expect(op.createAuthorizationResponse(verifiedAuthReqWithJWT, {})).rejects.toThrow( - Error('authentication request expects a verifiable presentation in the response'), + Error('vp_token is present, but no presentation definitions or dcql query provided'), ) expect(verifiedAuthReqWithJWT.payload?.['registration'].client_name).toEqual(VERIFIER_NAME_FOR_CLIENT) diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index 52981b78..be7fc1fb 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -425,10 +425,10 @@ export class RP { nonce, verification: mergeVerificationOpts(this._verifyResponseOptions, opts), ...(opts?.presentationDefinitions && !opts?.dcqlQuery && { - presentationDefinitions: this._verifyResponseOptions.presentationDefinitions + presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions }), - ...(opts?.dcqlQuery && { - dcqlQuery: this._verifyResponseOptions.dcqlQuery + ...(opts?.dcqlQuery && !opts?.presentationDefinitions && { + dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery }) } } From 3cc42b15d50e87ce5dd7b839199c840a2fcaed30 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 30 Dec 2024 14:12:48 +0100 Subject: [PATCH 34/60] Fix: Removed skip from tests that are running successfully --- packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index a5e63522..059c20d5 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -84,7 +84,7 @@ function getVCs(): OriginalVerifiableCredential[] { return [SD_JWT_VC] } -describe.skip('RP and OP interaction should', () => { +describe('RP and OP interaction should', () => { // FIXME SDK-45 Uniresolver failing it('succeed when calling with presentation definitions and right verifiable presentation', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') From 88ce80cfb3d44b3605761f95440128984e813201 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 31 Dec 2024 14:03:49 +0100 Subject: [PATCH 35/60] chore: added DCQL tests --- .../siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 137 +++++++++++++++++- .../AuthorizationRequest.ts | 2 +- .../lib/helpers/SIOPSpecVersion.ts | 2 +- 3 files changed, 137 insertions(+), 4 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index 059c20d5..c6fbda06 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -1,6 +1,8 @@ -import { SigningAlgo } from '@sphereon/oid4vc-common' +import { defaultHasher, SigningAlgo } from '@sphereon/oid4vc-common' import { IPresentationDefinition } from '@sphereon/pex' -import { OriginalVerifiableCredential } from '@sphereon/ssi-types' +import { decodeSdJwtVc, OriginalVerifiableCredential } from '@sphereon/ssi-types' +import { DcqlCredentialRepresentation, DcqlQuery } from 'dcql' +import { Json } from 'dcql/dist/src/u-dcql' import { OP, @@ -10,6 +12,7 @@ import { PresentationVerificationCallback, PropertyTarget, ResponseIss, + ResponseMode, ResponseType, RevocationVerification, RP, @@ -80,6 +83,21 @@ function getPresentationDefinition(): IPresentationDefinition { } } +const sdJwtVcQuery: DcqlQuery = { + credentials: [ + { + id: 'my_credential', + format: 'vc+sd-jwt', + meta: { + vct_values: ['https://high-assurance.com/StateBusinessLicense'], + }, + claims: [{ path: ['license', 'number'] }, { path: ['user', 'name'] }], + }, + ], +} + +DcqlQuery.validate(sdJwtVcQuery) + function getVCs(): OriginalVerifiableCredential[] { return [SD_JWT_VC] } @@ -326,4 +344,119 @@ describe('RP and OP interaction should', () => { expect(verifiedAuthResponseWithJWT.oid4vpSubmission?.nonce).toEqual('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') expect(verifiedAuthResponseWithJWT.idToken).toBeUndefined() }) + + it('succeed when calling with DCQL and right verifiable presentation', async () => { + const opMock = await mockedGetEnterpriseAuthToken('OP') + const opMockEntity = { + ...opMock, + didKey: `${opMock.did}#controller`, + } + const rpMock = await mockedGetEnterpriseAuthToken('RP') + const rpMockEntity = { + ...rpMock, + didKey: `${rpMock.did}#controller`, + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const presentationVerificationCallback: PresentationVerificationCallback = async (_args) => { + return { verified: true } + } + + const resolver = getResolver('ethr') + const rp = RP.builder({ requestVersion: SupportedVersion.SIOPv2_D12_OID4VP_D20 }) + .withClientId(rpMockEntity.did) + .withScope('test') + .withHasher(pexHasher) + .withResponseType([ResponseType.ID_TOKEN, ResponseType.VP_TOKEN]) + .withResponseMode(ResponseMode.DIRECT_POST) + .withRedirectUri(EXAMPLE_REDIRECT_URL) + .withDcqlQuery(JSON.stringify(sdJwtVcQuery), [PropertyTarget.REQUEST_OBJECT]) + .withPresentationVerification(presentationVerificationCallback) + .withRevocationVerification(RevocationVerification.NEVER) + .withRequestBy(PassBy.VALUE) + .withCreateJwtCallback(internalSignature(rpMockEntity.hexPrivateKey, rpMockEntity.did, `${rpMockEntity.did}#controller`, SigningAlgo.ES256K)) + .withAuthorizationEndpoint('www.myauthorizationendpoint.com') + .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) + .withClientMetadata({ + client_id: WELL_KNOWN_OPENID_FEDERATION, + idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], + requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + responseTypesSupported: [ResponseType.ID_TOKEN], + vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, + scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], + subjectTypesSupported: [SubjectType.PAIRWISE], + subject_syntax_types_supported: ['did', 'did:key'], + passBy: PassBy.VALUE, + logo_uri: VERIFIER_LOGO_FOR_CLIENT, + clientName: VERIFIER_NAME_FOR_CLIENT, + 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100322', + clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, + 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, + }) + .build() + + const op = OP.builder() + .withPresentationSignCallback(sdJwtVcPresentationSignCallback) + .withExpiresIn(1000) + .withHasher(pexHasher) + .withCreateJwtCallback(internalSignature(opMockEntity.hexPrivateKey, opMockEntity.did, `${opMockEntity.did}#controller`, SigningAlgo.ES256K)) + .withVerifyJwtCallback(getVerifyJwtCallback(resolver)) + .withRegistration({ + authorizationEndpoint: 'www.myauthorizationendpoint.com', + idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA], + issuer: ResponseIss.SELF_ISSUED_V2, + requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256], + responseTypesSupported: [ResponseType.ID_TOKEN, ResponseType.VP_TOKEN], + vpFormats: { jwt_vc: { alg: [SigningAlgo.EDDSA] } }, + scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID], + subjectTypesSupported: [SubjectType.PAIRWISE], + subject_syntax_types_supported: [], + passBy: PassBy.VALUE, + logo_uri: VERIFIER_LOGO_FOR_CLIENT, + clientName: VERIFIER_NAME_FOR_CLIENT, + 'clientName#nl-NL': VERIFIER_NAME_FOR_CLIENT_NL + '2022100323', + clientPurpose: VERIFIERZ_PURPOSE_TO_VERIFY, + 'clientPurpose#nl-NL': VERIFIERZ_PURPOSE_TO_VERIFY_NL, + }) + .withSupportedVersions(SupportedVersion.SIOPv2_D12_OID4VP_D20) + .build() + + const requestURI = await rp.createAuthorizationRequestURI({ + correlationId: '1234', + nonce: 'qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg', + state: 'b32f0087fc9816eb813fd11f', + }) + + // Let's test the parsing + const parsedAuthReqURI = await op.parseAuthorizationRequestURI(requestURI.encodedUri) + expect(parsedAuthReqURI.authorizationRequestPayload).toBeDefined() + expect(parsedAuthReqURI.requestObjectJwt).toBeDefined() + + if (!parsedAuthReqURI.requestObjectJwt) throw new Error('requestObjectJwt is undefined') + const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) + expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) + + const dcqlCredentials: DcqlCredentialRepresentation[] = getVCs().map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json } })) + + const queryResult = DcqlQuery.query(sdJwtVcQuery, dcqlCredentials) + + const encodedPresentationRecord: { [x: string]: string | { [x: string]: Json } } = {} + + for (const [key, _] of Object.entries(queryResult.credential_matches)) { + encodedPresentationRecord[key] = getVCs()[0] as string | { [x: string]: Json } + } + + const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { + dcqlQuery: { encodedPresentationRecord }, + }) + expect(authenticationResponseWithJWT.response.payload).toBeDefined() + expect(authenticationResponseWithJWT.response.idToken).toBeDefined() + + const verifiedAuthResponseWithJWT = await rp.verifyAuthorizationResponse(authenticationResponseWithJWT.response.payload, { + dcqlQuery: sdJwtVcQuery, + }) + + expect(verifiedAuthResponseWithJWT.idToken?.jwt).toBeDefined() + expect(verifiedAuthResponseWithJWT.idToken?.payload.nonce).toMatch('qBrR7mqnY3Qr49dAZycPF8FzgE83m6H0c2l0bzP4xSg') + }) }) diff --git a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts index aeb4b15b..dc6bc93e 100644 --- a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts +++ b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts @@ -2,7 +2,7 @@ import { parseJWT } from '@sphereon/oid4vc-common' import { DcqlQuery } from 'dcql' import { PresentationDefinitionWithLocation } from '../authorization-response' -import { findValidDcqlQuery } from '../authorization-response/Dcql' +import { findValidDcqlQuery } from '../authorization-response' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { fetchByReferenceOrUseByValue, removeNullUndefined } from '../helpers' import { authorizationRequestVersionDiscovery } from '../helpers/SIOPSpecVersion' diff --git a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts index 5e41e4e8..8efa2b9a 100644 --- a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts +++ b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts @@ -44,7 +44,7 @@ export const authorizationRequestVersionDiscovery = (authorizationRequest: Autho !authorizationRequestCopy.registration_uri && !authorizationRequestCopy.registration && !(authorizationRequestCopy.claims && 'vp_token' in authorizationRequestCopy.claims) && - authorizationRequestCopy.response_mode !== ResponseMode.POST // Post has been replaced by direct post + authorizationRequestCopy.response_mode !== ResponseMode.DIRECT_POST // Post has been replaced by direct post ) { versions.push(SupportedVersion.SIOPv2_D12_OID4VP_D20) } From e5a1854908dcbcc0744c54834897f35e615c1845 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Thu, 2 Jan 2025 18:11:34 +0100 Subject: [PATCH 36/60] Fix: Nonce was searched in the wrong place --- packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 6 ++++-- .../siop-oid4vp/lib/authorization-response/OpenID4VP.ts | 7 +------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index c6fbda06..c84a67af 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -40,6 +40,7 @@ const EXAMPLE_REDIRECT_URL = 'https://acme.com/hello' const HOLDER_DID = 'did:example:ebfeb1f712ebc6f1c276e12ec21' const SD_JWT_VC = 'eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCJ9.eyJpYXQiOjE3MDA0NjQ3MzYwNzYsImlzcyI6ImRpZDprZXk6c29tZS1yYW5kb20tZGlkLWtleSIsIm5iZiI6MTcwMDQ2NDczNjE3NiwidmN0IjoiaHR0cHM6Ly9oaWdoLWFzc3VyYW5jZS5jb20vU3RhdGVCdXNpbmVzc0xpY2Vuc2UiLCJ1c2VyIjp7Il9zZCI6WyI5QmhOVDVsSG5QVmpqQUp3TnR0NDIzM216MFVVMUd3RmFmLWVNWkFQV0JNIiwiSVl5d1FQZl8tNE9hY2Z2S2l1cjRlSnFMa1ZleWRxcnQ1Y2UwMGJReWNNZyIsIlNoZWM2TUNLakIxeHlCVl91QUtvLURlS3ZvQllYbUdBd2VGTWFsd05xbUEiLCJXTXpiR3BZYmhZMkdoNU9pWTRHc2hRU1dQREtSeGVPZndaNEhaQW5YS1RZIiwiajZ6ZFg1OUJYZHlTNFFaTGJITWJ0MzJpenRzWXdkZzRjNkpzWUxNc3ZaMCIsInhKR3Radm41cFM4VEhqVFlJZ3MwS1N5VC1uR3BSR3hDVnp6c1ZEbmMyWkUiXX0sImxpY2Vuc2UiOnsibnVtYmVyIjoxMH0sImNuZiI6eyJqd2siOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJUQ0FFUjE5WnZ1M09IRjRqNFc0dmZTVm9ISVAxSUxpbERsczd2Q2VHZW1jIiwieSI6Ilp4amlXV2JaTVFHSFZXS1ZRNGhiU0lpcnNWZnVlY0NFNnQ0alQ5RjJIWlEifX0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIl90YnpMeHBaeDBQVHVzV2hPOHRUZlVYU2ZzQjVlLUtrbzl3dmZaaFJrYVkiLCJ1WmNQaHdUTmN4LXpNQU1zemlYMkFfOXlJTGpQSEhobDhEd2pvVXJLVVdZIl19.HAcudVInhNpXkTPQGNosjKTFRJWgKj90NpfloRaDQchGd4zxc1ChWTCCPXzUXTBypASKrzgjZCiXlTr0bzmLAg~WyJHeDZHRUZvR2t6WUpWLVNRMWlDREdBIiwiZGF0ZU9mQmlydGgiLCIyMDAwMDEwMSJd~WyJ1LUt3cmJvMkZfTExQekdSZE1XLUtBIiwibmFtZSIsIkpvaG4iXQ~WyJNV1ZieGJqVFZxUXdLS3h2UGVZdWlnIiwibGFzdE5hbWUiLCJEb2UiXQ~' +const KB_SD_JWT_PRESENTATION = 'eyJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6a2V5OnNvbWUtcmFuZG9tLWRpZC1rZXkiLCJpYXQiOjE3MzU4MzY0NzY1NjksInZjdCI6Imh0dHBzOi8vaGlnaC1hc3N1cmFuY2UuY29tL1N0YXRlQnVzaW5lc3NMaWNlbnNlIiwiX3NkIjpbIk5ub3U2OGN6VG9qQWY0Z3dIMmJiNFBaWHB4WHJzQ29oWm5CbEZvQ293TTAiLCJ1ajZZZVZwSnRwUjhVWHRpbmVDOGM5LXpTRFJVQzJzSGhsRkNNNWtkLXlNIl0sIl9zZF9hbGciOiJzaGEtMjU2In0.X1pNBBmR-7h6SgxtmZY9GL_nSBzoIvWNw7nqqgJVCnSEbvyTjqTgu4bLSPKeaxf1jY2zHJK1jdxiDzIizRZ0gA~WyI4OTE4YjkxZGFjMzk1OTdkIiwidXNlciIseyJkYXRlX29mX2JpcnRoIjoiMDEvMDEvMTk3MCIsIl9zZCI6WyJ6UE8zb1RCT3BxMmRNcWQtekt5SmF2UlQyWVIwSHBPaV9jczZRajEtVmR3Il19XQ~WyIyOTc4NTNiODE5MTI0MTJkIiwibmFtZSIsIkpvaG4iXQ~WyJkYjEzNDQ4NTgxMzY0M2JlIiwibGljZW5zZSIseyJfc2QiOlsiWUFUR3A3TGxjNEMtTWtYWkZWTEF6RHRtbDFTMVpFWFFyTW5CdmVDWVFwayJdfV0~WyJlOTc3MzhiNmM0OGNhMWJlIiwibnVtYmVyIiwxMF0~eyJ0eXAiOiJrYitqd3QiLCJhbGciOiJFUzI1NiJ9.eyJpYXQiOjE3MzU4MzY0NzYsImF1ZCI6Imh0dHBzOi8vZXhhbXBsZS5jb20iLCJub25jZSI6InFCclI3bXFuWTNRcjQ5ZEFaeWNQRjhGemdFODNtNkgwYzJsMGJ6UDR4U2ciLCJjdXN0b20iOiJkYXRhIiwic2RfaGFzaCI6IlVwYzNYQWpzRU1mdnVmSzJ5Q3RkNDZXUFJmTDVfVDc4UThEZVNZQXlEX28ifQ.Crw56nLFFnVulRQElpq9HoskdKIyd5Mj6vg9UVNSWfhxQ0oGe10RHtifUv4BiFharSvWN99y_DnkhCPu1sPIYw' function getPresentationDefinition(): IPresentationDefinition { return { @@ -436,14 +437,15 @@ describe('RP and OP interaction should', () => { const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) - const dcqlCredentials: DcqlCredentialRepresentation[] = getVCs().map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json } })) + // FIXME kb-sd-jwts are not working with pex, so the presentation was not added to getVCs(...) + const dcqlCredentials: DcqlCredentialRepresentation[] = [KB_SD_JWT_PRESENTATION].map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json } })) const queryResult = DcqlQuery.query(sdJwtVcQuery, dcqlCredentials) const encodedPresentationRecord: { [x: string]: string | { [x: string]: Json } } = {} for (const [key, _] of Object.entries(queryResult.credential_matches)) { - encodedPresentationRecord[key] = getVCs()[0] as string | { [x: string]: Json } + encodedPresentationRecord[key] = KB_SD_JWT_PRESENTATION as string | { [x: string]: Json } } const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 38cd6e8f..e290ca24 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -1,4 +1,3 @@ -import { parseJWT } from '@sphereon/oid4vc-common' import { IPresentationDefinition, PEX, PresentationSubmissionLocation } from '@sphereon/pex' import { Format } from '@sphereon/pex-models' import { @@ -43,11 +42,7 @@ export const extractNonceFromWrappedVerifiablePresentation = (wrappedVp: Wrapped // TODO: replace this once `kbJwt.payload` is available on the decoded sd-jwt (pr in ssi-sdk) // If it doesn't end with ~, it contains a kbJwt if (!wrappedVp.presentation.compactSdJwtVc.endsWith('~')) { - const kbJwt = wrappedVp.presentation.compactSdJwtVc.split('~').pop() - - const { payload } = parseJWT(kbJwt) - - return payload.nonce + return wrappedVp.presentation.kbJwt.payload.nonce } // No kb-jwt means no nonce (error will be handled later) From 1c2838f6a8f925088ec91457be2e3f37e9b04ed1 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Fri, 3 Jan 2025 15:17:20 +0100 Subject: [PATCH 37/60] Fix: Fixed the SD-JWT sign callback and added extra DCQL test --- .../siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 71 ++++++++++++++++++- .../siop-oid4vp/lib/__tests__/TestUtils.ts | 61 +++++++++++++--- packages/siop-oid4vp/package.json | 3 + pnpm-lock.yaml | 46 ++++++++++++ 4 files changed, 168 insertions(+), 13 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index c84a67af..d2614c30 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -437,11 +437,78 @@ describe('RP and OP interaction should', () => { const verifiedAuthReqWithJWT = await op.verifyAuthorizationRequest(parsedAuthReqURI.requestObjectJwt) expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) - // FIXME kb-sd-jwts are not working with pex, so the presentation was not added to getVCs(...) - const dcqlCredentials: DcqlCredentialRepresentation[] = [KB_SD_JWT_PRESENTATION].map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json } })) + // The KB property is added to the JWT when the presentation is signed. Passing a VC will make the test fail + const dcqlCredentials: DcqlCredentialRepresentation[] = [KB_SD_JWT_PRESENTATION].map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json }, vct: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload.vct } )) const queryResult = DcqlQuery.query(sdJwtVcQuery, dcqlCredentials) + expect(queryResult).toEqual({ + "canBeSatisfied": true, + "credential_matches": { + "my_credential": { + "all": [ + [ + { + "credential_index": 0, + "output": { + "claims": { + "license": { + "number": 10 + }, + "user": { + "name": "John" + } + }, + "vct": "https://high-assurance.com/StateBusinessLicense" + }, + "success": true, + "typed": true + } + ] + ], + "credential_index": 0, + "output": { + "claims": { + "license": { + "number": 10 + }, + "user": { + "name": "John" + } + }, + "vct": "https://high-assurance.com/StateBusinessLicense" + }, + "success": true, + "typed": true + } + }, + "credentials": [ + { + "claims": [ + { + "path": [ + "license", + "number" + ] + }, + { + "path": [ + "user", + "name" + ] + } + ], + "format": "vc+sd-jwt", + "id": "my_credential", + "meta": { + "vct_values": [ + "https://high-assurance.com/StateBusinessLicense" + ] + } + } + ] + }) + const encodedPresentationRecord: { [x: string]: string | { [x: string]: Json } } = {} for (const [key, _] of Object.entries(queryResult.credential_matches)) { diff --git a/packages/siop-oid4vp/lib/__tests__/TestUtils.ts b/packages/siop-oid4vp/lib/__tests__/TestUtils.ts index bf073abe..33f30091 100644 --- a/packages/siop-oid4vp/lib/__tests__/TestUtils.ts +++ b/packages/siop-oid4vp/lib/__tests__/TestUtils.ts @@ -2,9 +2,11 @@ // @ts-ignore import crypto, { createHash } from 'crypto' +import { digest, ES256, generateSalt } from '@sd-jwt/crypto-nodejs' +import { SDJwtVcInstance } from '@sd-jwt/sd-jwt-vc' import { JwtPayload, parseJWT, SigningAlgo, uuidv4 } from '@sphereon/oid4vc-common' import { PartialSdJwtDecodedVerifiableCredential } from '@sphereon/pex/dist/main/lib' -import { IProofType } from '@sphereon/ssi-types' +import { IProofType, SdJwtVcKbJwtPayload } from '@sphereon/ssi-types' // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import base58 from 'bs58' @@ -26,7 +28,7 @@ import { RPRegistrationMetadataPayload, Scope, SubjectSyntaxTypesSupportedValues, - SubjectType, + SubjectType } from '../' import SIOPErrors from '../types/Errors' @@ -38,9 +40,10 @@ import { VERIFIER_NAME_FOR_CLIENT, VERIFIER_NAME_FOR_CLIENT_NL, VERIFIERZ_PURPOSE_TO_VERIFY, - VERIFIERZ_PURPOSE_TO_VERIFY_NL, + VERIFIERZ_PURPOSE_TO_VERIFY_NL } from './data/mockedData' + export interface TESTKEY { key: JWK did: string @@ -303,15 +306,51 @@ export const sdJwtVcPresentationSignCallback: PresentationSignCallback = async ( }, }) - const header = { - ...presentation.kbJwt.header, - alg: 'ES256K', + const createSignerVerifier = async () => { + const { privateKey, publicKey } = await ES256.generateKeyPair(); + return { + signer: await ES256.getSigner(privateKey), + verifier: await ES256.getVerifier(publicKey) + } } - const payload = { - ...presentation.kbJwt.payload, - aud: '123', + + const { signer, verifier } = await createSignerVerifier(); + + const sdjwt = new SDJwtVcInstance({ + signer, + signAlg: ES256.alg, + verifier, + hasher: digest, + saltGenerator: generateSalt, + kbSigner: signer, + kbSignAlg: ES256.alg, + kbVerifier: verifier + }) + + const claims = { + license: { + number: 10 + }, + user: { + name: 'John', + date_of_birth: '01/01/1970' + } } - const kbJwtCompact = `${Buffer.from(JSON.stringify(header)).toString('base64url')}.${Buffer.from(JSON.stringify(payload)).toString('base64url')}.signature` - return presentation.compactSdJwtVc + kbJwtCompact + const kbPayload: Omit = presentation.kbJwt.payload + + presentation.compactSdJwtVc = await sdjwt.present( + presentation.compactSdJwtVc, + { + user: { name: true }, + license: { number: true } + }, + { + kb: { + payload: kbPayload, + }, + }, + ); + + return presentation.compactSdJwtVc } diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 4e9ac139..ed9da3a3 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -44,6 +44,9 @@ "@digitalcredentials/ed25519-signature-2020": "^3.0.2", "@digitalcredentials/jsonld-signatures": "^9.3.2", "@digitalcredentials/vc": "^6.0.0", + "@sd-jwt/crypto-nodejs": "0.7.2", + "@sd-jwt/sd-jwt-vc": "0.7.2", + "@sd-jwt/types": "0.7.2", "@sphereon/wellknown-dids-client": "^0.1.3", "@sphereon/did-uni-client": "^0.6.2", "@transmute/did-key-ed25519": "^0.3.0-unstable.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f12956d5..df2ed3fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -523,6 +523,15 @@ importers: '@digitalcredentials/vc': specifier: ^6.0.0 version: 6.0.1(encoding@0.1.13)(expo@48.0.21(@babel/core@7.26.0)(encoding@0.1.13))(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1))(web-streams-polyfill@3.3.3) + '@sd-jwt/crypto-nodejs': + specifier: 0.7.2 + version: 0.7.2 + '@sd-jwt/sd-jwt-vc': + specifier: 0.7.2 + version: 0.7.2 + '@sd-jwt/types': + specifier: 0.7.2 + version: 0.7.2 '@sphereon/did-uni-client': specifier: ^0.6.2 version: 0.6.3(encoding@0.1.13) @@ -2451,14 +2460,30 @@ packages: '@scure/base@1.2.1': resolution: {integrity: sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==} + '@sd-jwt/core@0.7.2': + resolution: {integrity: sha512-vix1GplUFc1A9H42r/yXkg7cKYthggyqZEwlFdsBbn4xdZNE+AHVF4N7kPa1pPxipwN3UIHd4XnQ5MJV15mhsQ==} + engines: {node: '>=18'} + + '@sd-jwt/crypto-nodejs@0.7.2': + resolution: {integrity: sha512-7DHy1WBHwvXseiX+U7XA6jX4dX4Ins3Nxd12JhBSm+FJfIwU97FU/H0KlF6lLyi4a4nbY/O6U9wJjYI1PxA9sQ==} + engines: {node: '>=18'} + '@sd-jwt/decode@0.7.2': resolution: {integrity: sha512-dan2LSvK63SKwb62031G4r7TE4TaiI0EK1KbPXqS+LCXNkNDUHqhtYp9uOpj+grXceCsMtMa2f8VnUfsjmwHHg==} engines: {node: '>=18'} + '@sd-jwt/jwt-status-list@0.7.2': + resolution: {integrity: sha512-o/Mg/Zg21poFsPXuxtPD9sdXq2b/0L+rb9gxU2k1rp1aT+DWmqD0k8v0Ttr2tlMc8l1xXQNA8FLXbL1AdLRmbQ==} + engines: {node: '>=18'} + '@sd-jwt/present@0.7.2': resolution: {integrity: sha512-mQV85u2+mLLy2VZ9Wx2zpaB6yTDnbhCfWkP7eeCrzJQHBKAAHko8GrylEFmLKewFIcajS/r4lT/zHOsCkp5pZw==} engines: {node: '>=18'} + '@sd-jwt/sd-jwt-vc@0.7.2': + resolution: {integrity: sha512-rryYmnoJHRSNqHcrs0Atta+bfJzU2yT7mYumR2D4lTfxJKWZd0OHHFq57uZSEm/wXPI6uytUJXYbEboCqLUAtw==} + engines: {node: '>=18'} + '@sd-jwt/types@0.7.2': resolution: {integrity: sha512-1NRKowiW0ZiB9SGLApLPBH4Xk8gDQJ+nA9NdZ+uy6MmJKLEwjuJxO7yTvRIv/jX/0/Ebh339S7Kq4RD2AiFuRg==} engines: {node: '>=18'} @@ -11774,17 +11799,38 @@ snapshots: '@scure/base@1.2.1': {} + '@sd-jwt/core@0.7.2': + dependencies: + '@sd-jwt/decode': 0.7.2 + '@sd-jwt/present': 0.7.2 + '@sd-jwt/types': 0.7.2 + '@sd-jwt/utils': 0.7.2 + + '@sd-jwt/crypto-nodejs@0.7.2': {} + '@sd-jwt/decode@0.7.2': dependencies: '@sd-jwt/types': 0.7.2 '@sd-jwt/utils': 0.7.2 + '@sd-jwt/jwt-status-list@0.7.2': + dependencies: + '@sd-jwt/types': 0.7.2 + base64url: 3.0.1 + pako: 2.1.0 + '@sd-jwt/present@0.7.2': dependencies: '@sd-jwt/decode': 0.7.2 '@sd-jwt/types': 0.7.2 '@sd-jwt/utils': 0.7.2 + '@sd-jwt/sd-jwt-vc@0.7.2': + dependencies: + '@sd-jwt/core': 0.7.2 + '@sd-jwt/jwt-status-list': 0.7.2 + '@sd-jwt/utils': 0.7.2 + '@sd-jwt/types@0.7.2': {} '@sd-jwt/utils@0.7.2': From 5674a275c8ed7f8e0b9c58599131735218f20c90 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Fri, 3 Jan 2025 16:14:21 +0100 Subject: [PATCH 38/60] Fix: Updated the response mode in test --- packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts b/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts index f916e415..8045e1f7 100644 --- a/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts @@ -234,7 +234,7 @@ describe('Mattr OID4VP v18 credential offer', () => { }) expect(verification).toBeDefined() - expect(verification.versions).toEqual([SupportedVersion.SIOPv2_D12_OID4VP_D20, SupportedVersion.SIOPv2_D12_OID4VP_D18]) + expect(verification.versions).toEqual([SupportedVersion.SIOPv2_D12_OID4VP_D18]) /** * pd value: {"id":"dae5d9b6-8145-4297-99b2-b8fcc5abb5ad","input_descriptors":[{"id":"OpenBadgeCredential","format":{"jwt_vc_json":{"alg":["EdDSA"]},"jwt_vc":{"alg":["EdDSA"]}},"constraints":{"fields":[{"path":["$.vc.type"],"filter":{"type":"array","items":{"type":"string"},"contains":{"const":"OpenBadgeCredential"}}}]}}]} From fd6a07bf6e92dbbc8ed77d4f7f5a5fa8bc7c34c0 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 8 Jan 2025 10:27:58 +0100 Subject: [PATCH 39/60] Refactor: Disabled tests again --- packages/siop-oid4vp/lib/__tests__/IT.spec.ts | 2 +- packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/IT.spec.ts b/packages/siop-oid4vp/lib/__tests__/IT.spec.ts index 8bb15898..ee892a58 100644 --- a/packages/siop-oid4vp/lib/__tests__/IT.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/IT.spec.ts @@ -141,7 +141,7 @@ function getVCs(): IVerifiableCredential[] { return vcs } -describe('RP and OP interaction should', () => { +describe.skip('RP and OP interaction should', () => { // FIXME SDK-45 Uniresolver failing it( 'succeed when calling each other in the full flow', diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index d2614c30..457a983b 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -103,7 +103,7 @@ function getVCs(): OriginalVerifiableCredential[] { return [SD_JWT_VC] } -describe('RP and OP interaction should', () => { +describe.skip('RP and OP interaction should', () => { // FIXME SDK-45 Uniresolver failing it('succeed when calling with presentation definitions and right verifiable presentation', async () => { const opMock = await mockedGetEnterpriseAuthToken('OP') From d0023791635f3866bfc09011d6a79a407b9d22d2 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 8 Jan 2025 13:42:31 +0100 Subject: [PATCH 40/60] Refactor: Rolled back the changes in response type and updated DCQL library. --- package.json | 2 +- .../AuthenticationResponse.response.spec.ts | 13 ++++---- .../siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 10 +++---- .../lib/__tests__/e2e/mattr.launchpad.spec.ts | 2 +- .../lib/helpers/SIOPSpecVersion.ts | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 30 +++++++++---------- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 3fb16fb7..22d624ea 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "resolutions": { "@sphereon/ssi-types": "0.32.0", - "dcql": "0.2.11", + "dcql": "0.2.17", "node-fetch": "2.6.12" }, "prettier": { diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index a82a730e..368ff707 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -8,7 +8,7 @@ import { IVerifiablePresentation, OriginalVerifiableCredential, } from '@sphereon/ssi-types' -import { DcqlCredentialRepresentation, DcqlPresentationRecord, DcqlQuery, DcqlQueryResult } from 'dcql' +import { DcqlCredential, DcqlPresentation, DcqlQuery, DcqlQueryResult } from 'dcql' import { AuthorizationResponse, @@ -28,7 +28,7 @@ import { VerifyAuthorizationRequestOpts, VPTokenLocation, } from '..' -import { createPresentationSubmission } from '../authorization-response/OpenID4VP' +import { createPresentationSubmission } from '../authorization-response' import SIOPErrors from '../types/Errors' import { getCreateJwtCallback, getVerifyJwtCallback } from './DidJwtTestUtils' @@ -749,21 +749,22 @@ describe('create JWT from Request JWT should', () => { }, } - const vc: DcqlCredentialRepresentation = { + const vc: DcqlCredential = { + credential_format: 'vc+sd-jwt', vct: sdjwt.decodedPayload.payload.vct, claims: sdjwt.decodedPayload.payload, } const dcqlQueryResult: DcqlQueryResult = DcqlQuery.query(dcqlQuery, [vc]) - const presentation: DcqlPresentationRecord.Output = {} + const presentation: DcqlPresentation.Output = {} for (const [key, value] of Object.entries(dcqlQueryResult.credential_matches)) { if (value.success) { presentation[key] = sdjwt.compactJwtVc } } - const encodedPresentationRecord = DcqlPresentationRecord.parse(presentation) + const dcqlPresentation = DcqlPresentation.parse(presentation) const responseOpts: AuthorizationResponseOpts = { responseURI: EXAMPLE_REDIRECT_URL, @@ -776,7 +777,7 @@ describe('create JWT from Request JWT should', () => { }), jwtIssuer: { method: 'did', didUrl: `${mockResEntity.did}#controller`, alg: SigningAlgo.ES256K }, dcqlQuery: { - encodedPresentationRecord, + dcqlPresentation }, responseMode: ResponseMode.DIRECT_POST, } diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index 457a983b..36f50a26 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -1,7 +1,7 @@ import { defaultHasher, SigningAlgo } from '@sphereon/oid4vc-common' import { IPresentationDefinition } from '@sphereon/pex' import { decodeSdJwtVc, OriginalVerifiableCredential } from '@sphereon/ssi-types' -import { DcqlCredentialRepresentation, DcqlQuery } from 'dcql' +import { DcqlCredential, DcqlQuery } from 'dcql' import { Json } from 'dcql/dist/src/u-dcql' import { @@ -438,7 +438,7 @@ describe.skip('RP and OP interaction should', () => { expect(verifiedAuthReqWithJWT.issuer).toMatch(rpMockEntity.did) // The KB property is added to the JWT when the presentation is signed. Passing a VC will make the test fail - const dcqlCredentials: DcqlCredentialRepresentation[] = [KB_SD_JWT_PRESENTATION].map(vc => ({ claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json }, vct: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload.vct } )) + const dcqlCredentials: DcqlCredential[] = [KB_SD_JWT_PRESENTATION].map(vc => ({ credential_format: 'vc+sd-jwt', claims: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload as { [x: string]: Json }, vct: decodeSdJwtVc(vc as string, defaultHasher).decodedPayload.vct } )) const queryResult = DcqlQuery.query(sdJwtVcQuery, dcqlCredentials) @@ -509,14 +509,14 @@ describe.skip('RP and OP interaction should', () => { ] }) - const encodedPresentationRecord: { [x: string]: string | { [x: string]: Json } } = {} + const dcqlPresentation: { [x: string]: string | { [x: string]: Json } } = {} for (const [key, _] of Object.entries(queryResult.credential_matches)) { - encodedPresentationRecord[key] = KB_SD_JWT_PRESENTATION as string | { [x: string]: Json } + dcqlPresentation[key] = KB_SD_JWT_PRESENTATION as string | { [x: string]: Json } } const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { - dcqlQuery: { encodedPresentationRecord }, + dcqlQuery: { dcqlPresentation }, }) expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() diff --git a/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts b/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts index 8045e1f7..f916e415 100644 --- a/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/e2e/mattr.launchpad.spec.ts @@ -234,7 +234,7 @@ describe('Mattr OID4VP v18 credential offer', () => { }) expect(verification).toBeDefined() - expect(verification.versions).toEqual([SupportedVersion.SIOPv2_D12_OID4VP_D18]) + expect(verification.versions).toEqual([SupportedVersion.SIOPv2_D12_OID4VP_D20, SupportedVersion.SIOPv2_D12_OID4VP_D18]) /** * pd value: {"id":"dae5d9b6-8145-4297-99b2-b8fcc5abb5ad","input_descriptors":[{"id":"OpenBadgeCredential","format":{"jwt_vc_json":{"alg":["EdDSA"]},"jwt_vc":{"alg":["EdDSA"]}},"constraints":{"fields":[{"path":["$.vc.type"],"filter":{"type":"array","items":{"type":"string"},"contains":{"const":"OpenBadgeCredential"}}}]}}]} diff --git a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts index 8efa2b9a..5e41e4e8 100644 --- a/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts +++ b/packages/siop-oid4vp/lib/helpers/SIOPSpecVersion.ts @@ -44,7 +44,7 @@ export const authorizationRequestVersionDiscovery = (authorizationRequest: Autho !authorizationRequestCopy.registration_uri && !authorizationRequestCopy.registration && !(authorizationRequestCopy.claims && 'vp_token' in authorizationRequestCopy.claims) && - authorizationRequestCopy.response_mode !== ResponseMode.DIRECT_POST // Post has been replaced by direct post + authorizationRequestCopy.response_mode !== ResponseMode.POST // Post has been replaced by direct post ) { versions.push(SupportedVersion.SIOPv2_D12_OID4VP_D20) } diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index ed9da3a3..2a64b9ca 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.28", - "dcql": "0.2.11", + "dcql": "0.2.17", "@sphereon/pex-models": "^2.3.2", "@sphereon/ssi-types": "0.32.0", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df2ed3fd..c6c2bb15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: overrides: '@sphereon/ssi-types': 0.32.0 - dcql: 0.2.11 + dcql: 0.2.17 node-fetch: 2.6.12 importers: @@ -460,8 +460,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: 0.2.11 - version: 0.2.11(typescript@5.4.5) + specifier: 0.2.17 + version: 0.2.17(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -4033,8 +4033,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.11: - resolution: {integrity: sha512-hR8MuSx49b7JPoZztcFMSKEHc6iEE4l/Zs6aUsvMCWVa3qFWpuJRiJEp5Rh2+UkCAhsce94fbDpMdBTcS9zn7g==} + dcql@0.2.17: + resolution: {integrity: sha512-YKNJR2anEiWooUCg7cJt/QmSFxpBS+SJQurcsNA60+8qUrjOuroh1Wd+lka/yOAV2VUdRzdNY6ISouxTV6SUaQ==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -8395,16 +8395,16 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - valibot@0.37.0: - resolution: {integrity: sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==} + valibot@0.42.1: + resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} peerDependencies: typescript: '>=5' peerDependenciesMeta: typescript: optional: true - valibot@0.42.1: - resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} + valibot@1.0.0-beta.8: + resolution: {integrity: sha512-OPAwJZtowb0j91b+bd77+ny7D1VVzsCzD7Jl9waLUlMprTsfI9Y3HHbW3hAQD7wKDKHsmGEesuiYWaYvcZL2wg==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -13947,9 +13947,9 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.11(typescript@5.4.5): + dcql@0.2.17(typescript@5.4.5): dependencies: - valibot: 0.37.0(typescript@5.4.5) + valibot: 1.0.0-beta.8(typescript@5.4.5) transitivePeerDependencies: - typescript @@ -19613,14 +19613,14 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - valibot@0.37.0(typescript@5.4.5): - optionalDependencies: - typescript: 5.4.5 - valibot@0.42.1(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 + valibot@1.0.0-beta.8(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + valid-url@1.0.9: {} validate-npm-package-license@3.0.4: From 43420cfd58ff89f4fdfe6da329e9098b6ff99dfd Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 8 Jan 2025 14:34:58 +0100 Subject: [PATCH 41/60] refactor: Checking whether PDs and DCQL are present --- packages/siop-oid4vp/lib/rp/RP.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index be7fc1fb..e529aee8 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -415,6 +415,16 @@ export class RP { } } + const hasPD = (this._verifyResponseOptions.presentationDefinitions !== undefined && this._verifyResponseOptions.presentationDefinitions !== null || (Array.isArray(this._verifyResponseOptions.presentationDefinitions) && this._verifyResponseOptions.presentationDefinitions.length > 0)) || + (opts.presentationDefinitions !== undefined && opts.presentationDefinitions !== null || (Array.isArray(opts.presentationDefinitions) && opts.presentationDefinitions.length > 0)) + const hasDcql = (this._verifyResponseOptions.dcqlQuery !== undefined && this._verifyResponseOptions.dcqlQuery !== null) || (opts.dcqlQuery !== undefined && opts.dcqlQuery !== null) + + if (hasPD && hasDcql) { + throw Error(`Only Presentation Definitions or DCQL is required`) + } else if (!hasPD && !hasDcql) { + throw Error(`Either a Presentation Definition or DCQL is required`) + } + return { ...this._verifyResponseOptions, verifyJwtCallback: this._verifyResponseOptions.verifyJwtCallback, @@ -424,12 +434,8 @@ export class RP { state, nonce, verification: mergeVerificationOpts(this._verifyResponseOptions, opts), - ...(opts?.presentationDefinitions && !opts?.dcqlQuery && { - presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions - }), - ...(opts?.dcqlQuery && !opts?.presentationDefinitions && { - dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery - }) + presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions, + dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery } } From 44821ee73aaea1f5339d25fa1f92e27f6ecc8092 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Wed, 8 Jan 2025 14:52:53 +0100 Subject: [PATCH 42/60] refactor: Removed pnpm version limitation --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 22d624ea..2c1839dd 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,5 @@ "OIDC4VP", "OID4VCI", "OID4VP" - ], - "packageManager": "pnpm@9.6.0+sha256.dae0f7e822c56b20979bb5965e3b73b8bdabb6b8b8ef121da6d857508599ca35" + ] } From 8b78e933ebb11ad7c88d2427a9766c090bac6eed Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 12:46:36 +0100 Subject: [PATCH 43/60] chore: throw reason for VERIFIABLE_PRESENTATION_SIGNATURE_NOT_VALID --- .../lib/authorization-response/PresentationExchange.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts b/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts index 66f717b2..6891bed8 100644 --- a/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts +++ b/packages/siop-oid4vp/lib/authorization-response/PresentationExchange.ts @@ -397,7 +397,8 @@ export class PresentationExchange { try { verificationResult = await verifyPresentationCallback(presentation as W3CVerifiablePresentation, evaluationResults.value!) } catch (error: unknown) { - throw new Error(SIOPErrors.VERIFIABLE_PRESENTATION_SIGNATURE_NOT_VALID) + const errorMessage = error instanceof Error ? error.message : String(error) + throw new Error(`${SIOPErrors.VERIFIABLE_PRESENTATION_SIGNATURE_NOT_VALID}: ${errorMessage}`) } if (!verificationResult.verified) { From d6d751a1aa3e13686915c353458b292882edff2e Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 13:55:49 +0100 Subject: [PATCH 44/60] chore: lib updates --- package.json | 2 +- packages/callback-example/package.json | 2 +- packages/client/package.json | 2 +- packages/common/package.json | 2 +- packages/issuer-rest/package.json | 2 +- packages/issuer/package.json | 2 +- packages/oid4vci-common/package.json | 2 +- .../AuthorizationResponse.ts | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 46 +++++++++---------- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index e1482a95..c54e1b0d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "node": ">=18" }, "resolutions": { - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "dcql": "0.2.11", "node-fetch": "2.6.12" }, diff --git a/packages/callback-example/package.json b/packages/callback-example/package.json index bb1dd3e1..b157f874 100644 --- a/packages/callback-example/package.json +++ b/packages/callback-example/package.json @@ -19,7 +19,7 @@ "@sphereon/oid4vci-client": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "jose": "^4.10.0" }, "devDependencies": { diff --git a/packages/client/package.json b/packages/client/package.json index 5e7acb8a..0389786f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,7 +17,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "cross-fetch": "^3.1.8", "debug": "^4.3.5" }, diff --git a/packages/common/package.json b/packages/common/package.json index 04ea2a3d..cf2238e9 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -10,7 +10,7 @@ "build:clean": "tsc --build --clean && tsc --build" }, "dependencies": { - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "jwt-decode": "^4.0.0", "sha.js": "^2.4.11", "uint8arrays": "3.1.1", diff --git a/packages/issuer-rest/package.json b/packages/issuer-rest/package.json index 5c3007e0..8cd4d858 100644 --- a/packages/issuer-rest/package.json +++ b/packages/issuer-rest/package.json @@ -15,7 +15,7 @@ "@sphereon/oid4vci-common": "workspace:*", "@sphereon/oid4vci-issuer": "workspace:*", "@sphereon/ssi-express-support": "0.30.2-feature.mdoc.funke2.367", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "cors": "^2.8.5", diff --git a/packages/issuer/package.json b/packages/issuer/package.json index ea3d1f4f..e35aa0c2 100644 --- a/packages/issuer/package.json +++ b/packages/issuer/package.json @@ -12,7 +12,7 @@ "dependencies": { "@sphereon/oid4vc-common": "workspace:*", "@sphereon/oid4vci-common": "workspace:*", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "uuid": "^9.0.0" }, "peerDependencies": { diff --git a/packages/oid4vci-common/package.json b/packages/oid4vci-common/package.json index ffcfdb85..5ae90beb 100644 --- a/packages/oid4vci-common/package.json +++ b/packages/oid4vci-common/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@sphereon/oid4vc-common": "workspace:*", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "cross-fetch": "^3.1.8", "debug": "^4.3.5", "jwt-decode": "^4.0.0", diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 0e2c8112..69078199 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -229,7 +229,7 @@ export class AuthorizationResponse { } public async getMergedProperty(key: string, opts?: { consistencyCheck?: boolean; hasher?: Hasher }): Promise { - const merged = await this.mergedPayloads(opts) + const merged = await this.mergedPayloads(opts) // FIXME this is really bad, expensive... return merged[key] as T } diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index 2e98f766..d10ab9cf 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -20,7 +20,7 @@ "@sphereon/pex": "5.0.0-unstable.28", "dcql": "0.2.11", "@sphereon/pex-models": "^2.3.2", - "@sphereon/ssi-types": "0.32.1-feature.VDX.341.27", + "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "cross-fetch": "^4.0.0", "debug": "^4.3.5", "events": "^3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73d98481..04068952 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: - '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.53 dcql: 0.2.11 node-fetch: 2.6.12 @@ -77,8 +77,8 @@ importers: specifier: workspace:* version: link:../issuer '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 jose: specifier: ^4.10.0 version: 4.15.9 @@ -120,8 +120,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -205,8 +205,8 @@ importers: packages/common: dependencies: '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -270,8 +270,8 @@ importers: specifier: workspace:* version: link:../oid4vci-common '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -313,8 +313,8 @@ importers: specifier: 0.30.2-feature.mdoc.funke2.367 version: 0.30.2-feature.mdoc.funke2.367 '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 awesome-qr: specifier: ^2.1.5-rc.0 version: 2.1.5-rc.0(encoding@0.1.13) @@ -405,8 +405,8 @@ importers: specifier: workspace:* version: link:../common '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 cross-fetch: specifier: ^3.1.8 version: 3.1.8(encoding@0.1.13) @@ -454,8 +454,8 @@ importers: specifier: ^2.3.2 version: 2.3.2 '@sphereon/ssi-types': - specifier: 0.32.1-feature.VDX.341.27 - version: 0.32.1-feature.VDX.341.27 + specifier: 0.32.1-feature.VDX.341.53 + version: 0.32.1-feature.VDX.341.53 cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) @@ -2565,8 +2565,8 @@ packages: '@sphereon/ssi-sdk-ext.key-utils@0.23.0': resolution: {integrity: sha512-BfULXvQmcUrBq2DqYxJHKnEoB2d5icu3TJ9GP2aP1WybSULTjL96Wv5r7QKgktcodKaL+F+oQ7r8sC9qBl1exw==} - '@sphereon/ssi-types@0.32.1-feature.VDX.341.27': - resolution: {integrity: sha512-Mw72f13IckggZmQ2uXlcq/gHgwoV+Mqtj3/SyBHZrxkvAq9LpWynImrlgiQDkBGlvpQ3chZ/ju8pQIPDTIqFWA==} + '@sphereon/ssi-types@0.32.1-feature.VDX.341.53': + resolution: {integrity: sha512-SC5GMqMZDILQJLGUddXjkVmSHIsDevp/ANVRGtLsWQK1pt3272eOA6Xq0yBMaAFmknYlisHMOf29JlYLJy/fZw==} '@sphereon/wellknown-dids-client@0.1.3': resolution: {integrity: sha512-TAT24L3RoXD8ocrkTcsz7HuJmgjNjdoV6IXP1p3DdaI/GqkynytXE3J1+F7vUFMRYwY5nW2RaXSgDQhrFJemaA==} @@ -10026,7 +10026,7 @@ snapshots: '@digitalcredentials/bnid@2.1.2(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1))': dependencies: '@digitalcredentials/base58-universal': 1.0.1 - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) yargs: 15.4.1 transitivePeerDependencies: - react-native @@ -11875,7 +11875,7 @@ snapshots: webcrypto-shim: 0.1.7 optionalDependencies: expo: 48.0.21(@babel/core@7.26.0)(encoding@0.1.13) - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': dependencies: @@ -11892,7 +11892,7 @@ snapshots: '@sd-jwt/present': 0.7.2 '@sd-jwt/types': 0.7.2 '@sphereon/pex-models': 2.3.2 - '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.53 ajv: 8.17.1 ajv-formats: 2.1.1(ajv@8.17.1) jwt-decode: 3.1.2 @@ -11944,7 +11944,7 @@ snapshots: - react-native-securerandom - supports-color - '@sphereon/ssi-types@0.32.1-feature.VDX.341.27': + '@sphereon/ssi-types@0.32.1-feature.VDX.341.53': dependencies: '@sd-jwt/decode': 0.7.2 '@sphereon/kmp-mdoc-core': 0.2.0-SNAPSHOT.26 @@ -11957,7 +11957,7 @@ snapshots: '@sphereon/wellknown-dids-client@0.1.3(encoding@0.1.13)': dependencies: - '@sphereon/ssi-types': 0.32.1-feature.VDX.341.27 + '@sphereon/ssi-types': 0.32.1-feature.VDX.341.53 cross-fetch: 3.1.8(encoding@0.1.13) jwt-decode: 3.1.2 transitivePeerDependencies: @@ -18213,7 +18213,7 @@ snapshots: react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) optional: true - react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)): + react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)): dependencies: base64-js: 1.5.1 react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) From 4ff1d70052db080d516e27b94555baef77232ea7 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 15:32:57 +0100 Subject: [PATCH 45/60] chore: dcql update --- package.json | 2 +- packages/siop-oid4vp/package.json | 2 +- pnpm-lock.yaml | 77 +++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c54e1b0d..a13ec126 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "resolutions": { "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", - "dcql": "0.2.11", + "dcql": "0.2.19", "node-fetch": "2.6.12" }, "prettier": { diff --git a/packages/siop-oid4vp/package.json b/packages/siop-oid4vp/package.json index aad9056a..4978ce14 100644 --- a/packages/siop-oid4vp/package.json +++ b/packages/siop-oid4vp/package.json @@ -18,7 +18,7 @@ "@sphereon/jarm": "workspace:*", "@sphereon/oid4vc-common": "workspace:*", "@sphereon/pex": "5.0.0-unstable.28", - "dcql": "0.2.17", + "dcql": "0.2.19", "@sphereon/pex-models": "^2.3.2", "@sphereon/ssi-types": "0.32.1-feature.VDX.341.53", "cross-fetch": "^4.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04068952..a90f84f8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: overrides: '@sphereon/ssi-types': 0.32.1-feature.VDX.341.53 - dcql: 0.2.11 + dcql: 0.2.19 node-fetch: 2.6.12 importers: @@ -460,8 +460,8 @@ importers: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) dcql: - specifier: 0.2.11 - version: 0.2.11(typescript@5.4.5) + specifier: 0.2.19 + version: 0.2.19(typescript@5.4.5) debug: specifier: ^4.3.5 version: 4.3.7 @@ -523,6 +523,15 @@ importers: '@digitalcredentials/vc': specifier: ^6.0.0 version: 6.0.1(encoding@0.1.13)(expo@48.0.21(@babel/core@7.26.0)(encoding@0.1.13))(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1))(web-streams-polyfill@3.3.3) + '@sd-jwt/crypto-nodejs': + specifier: 0.7.2 + version: 0.7.2 + '@sd-jwt/sd-jwt-vc': + specifier: 0.7.2 + version: 0.7.2 + '@sd-jwt/types': + specifier: 0.7.2 + version: 0.7.2 '@sphereon/did-uni-client': specifier: ^0.6.2 version: 0.6.3(encoding@0.1.13) @@ -2451,14 +2460,30 @@ packages: '@scure/base@1.2.1': resolution: {integrity: sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==} + '@sd-jwt/core@0.7.2': + resolution: {integrity: sha512-vix1GplUFc1A9H42r/yXkg7cKYthggyqZEwlFdsBbn4xdZNE+AHVF4N7kPa1pPxipwN3UIHd4XnQ5MJV15mhsQ==} + engines: {node: '>=18'} + + '@sd-jwt/crypto-nodejs@0.7.2': + resolution: {integrity: sha512-7DHy1WBHwvXseiX+U7XA6jX4dX4Ins3Nxd12JhBSm+FJfIwU97FU/H0KlF6lLyi4a4nbY/O6U9wJjYI1PxA9sQ==} + engines: {node: '>=18'} + '@sd-jwt/decode@0.7.2': resolution: {integrity: sha512-dan2LSvK63SKwb62031G4r7TE4TaiI0EK1KbPXqS+LCXNkNDUHqhtYp9uOpj+grXceCsMtMa2f8VnUfsjmwHHg==} engines: {node: '>=18'} + '@sd-jwt/jwt-status-list@0.7.2': + resolution: {integrity: sha512-o/Mg/Zg21poFsPXuxtPD9sdXq2b/0L+rb9gxU2k1rp1aT+DWmqD0k8v0Ttr2tlMc8l1xXQNA8FLXbL1AdLRmbQ==} + engines: {node: '>=18'} + '@sd-jwt/present@0.7.2': resolution: {integrity: sha512-mQV85u2+mLLy2VZ9Wx2zpaB6yTDnbhCfWkP7eeCrzJQHBKAAHko8GrylEFmLKewFIcajS/r4lT/zHOsCkp5pZw==} engines: {node: '>=18'} + '@sd-jwt/sd-jwt-vc@0.7.2': + resolution: {integrity: sha512-rryYmnoJHRSNqHcrs0Atta+bfJzU2yT7mYumR2D4lTfxJKWZd0OHHFq57uZSEm/wXPI6uytUJXYbEboCqLUAtw==} + engines: {node: '>=18'} + '@sd-jwt/types@0.7.2': resolution: {integrity: sha512-1NRKowiW0ZiB9SGLApLPBH4Xk8gDQJ+nA9NdZ+uy6MmJKLEwjuJxO7yTvRIv/jX/0/Ebh339S7Kq4RD2AiFuRg==} engines: {node: '>=18'} @@ -2540,6 +2565,7 @@ packages: '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': resolution: {integrity: sha512-QXJ6R8ENiZV2rPMbn06cw5JKwqUYN1kzVRbYfONqE1PEXx1noQ4md7uxr2zSczi0ubKkNcbyYDNtIMTZIhGzmQ==} + bundledDependencies: [] '@sphereon/pex-models@2.3.2': resolution: {integrity: sha512-foFxfLkRwcn/MOp/eht46Q7wsvpQGlO7aowowIIb5Tz9u97kYZ2kz6K2h2ODxWuv5CRA7Q0MY8XUBGE2lfOhOQ==} @@ -4007,8 +4033,8 @@ packages: dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - dcql@0.2.11: - resolution: {integrity: sha512-hR8MuSx49b7JPoZztcFMSKEHc6iEE4l/Zs6aUsvMCWVa3qFWpuJRiJEp5Rh2+UkCAhsce94fbDpMdBTcS9zn7g==} + dcql@0.2.19: + resolution: {integrity: sha512-/EvT8tArlg8zFsTQbRn6PijfeQ3nUwuEeCRDpptWcYqE8Wyt8J9Sb44gMPFzVCoIEb3R0M7Hl+XWkUMobC8jXQ==} debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -8369,16 +8395,16 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - valibot@0.37.0: - resolution: {integrity: sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==} + valibot@0.42.1: + resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} peerDependencies: typescript: '>=5' peerDependenciesMeta: typescript: optional: true - valibot@0.42.1: - resolution: {integrity: sha512-3keXV29Ar5b//Hqi4MbSdV7lfVp6zuYLZuA9V1PvQUsXqogr+u5lvLPLk3A4f74VUXDnf/JfWMN6sB+koJ/FFw==} + valibot@1.0.0-beta.8: + resolution: {integrity: sha512-OPAwJZtowb0j91b+bd77+ny7D1VVzsCzD7Jl9waLUlMprTsfI9Y3HHbW3hAQD7wKDKHsmGEesuiYWaYvcZL2wg==} peerDependencies: typescript: '>=5' peerDependenciesMeta: @@ -11773,17 +11799,38 @@ snapshots: '@scure/base@1.2.1': {} + '@sd-jwt/core@0.7.2': + dependencies: + '@sd-jwt/decode': 0.7.2 + '@sd-jwt/present': 0.7.2 + '@sd-jwt/types': 0.7.2 + '@sd-jwt/utils': 0.7.2 + + '@sd-jwt/crypto-nodejs@0.7.2': {} + '@sd-jwt/decode@0.7.2': dependencies: '@sd-jwt/types': 0.7.2 '@sd-jwt/utils': 0.7.2 + '@sd-jwt/jwt-status-list@0.7.2': + dependencies: + '@sd-jwt/types': 0.7.2 + base64url: 3.0.1 + pako: 2.1.0 + '@sd-jwt/present@0.7.2': dependencies: '@sd-jwt/decode': 0.7.2 '@sd-jwt/types': 0.7.2 '@sd-jwt/utils': 0.7.2 + '@sd-jwt/sd-jwt-vc@0.7.2': + dependencies: + '@sd-jwt/core': 0.7.2 + '@sd-jwt/jwt-status-list': 0.7.2 + '@sd-jwt/utils': 0.7.2 + '@sd-jwt/types@0.7.2': {} '@sd-jwt/utils@0.7.2': @@ -13900,9 +13947,9 @@ snapshots: dayjs@1.11.13: {} - dcql@0.2.11(typescript@5.4.5): + dcql@0.2.19(typescript@5.4.5): dependencies: - valibot: 0.37.0(typescript@5.4.5) + valibot: 1.0.0-beta.8(typescript@5.4.5) transitivePeerDependencies: - typescript @@ -19566,14 +19613,14 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - valibot@0.37.0(typescript@5.4.5): - optionalDependencies: - typescript: 5.4.5 - valibot@0.42.1(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 + valibot@1.0.0-beta.8(typescript@5.4.5): + optionalDependencies: + typescript: 5.4.5 + valid-url@1.0.9: {} validate-npm-package-license@3.0.4: From 7e8a5fd262b10ddc745462223b0f58b7bf7d84f2 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 15:57:49 +0100 Subject: [PATCH 46/60] chore: dcql fixes --- packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 8 ++++++-- packages/siop-oid4vp/lib/rp/RPBuilder.ts | 3 ++- packages/siop-oid4vp/lib/types/SIOP.types.ts | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index 36f50a26..1c504b52 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -2,7 +2,6 @@ import { defaultHasher, SigningAlgo } from '@sphereon/oid4vc-common' import { IPresentationDefinition } from '@sphereon/pex' import { decodeSdJwtVc, OriginalVerifiableCredential } from '@sphereon/ssi-types' import { DcqlCredential, DcqlQuery } from 'dcql' -import { Json } from 'dcql/dist/src/u-dcql' import { OP, @@ -35,6 +34,11 @@ import { jest.setTimeout(30000) +type Json = string | number | boolean | null | { // Not exported from dcql + [key: string]: Json; +} | Json[]; + + const EXAMPLE_REDIRECT_URL = 'https://acme.com/hello' const HOLDER_DID = 'did:example:ebfeb1f712ebc6f1c276e12ec21' @@ -371,7 +375,7 @@ describe.skip('RP and OP interaction should', () => { .withResponseType([ResponseType.ID_TOKEN, ResponseType.VP_TOKEN]) .withResponseMode(ResponseMode.DIRECT_POST) .withRedirectUri(EXAMPLE_REDIRECT_URL) - .withDcqlQuery(JSON.stringify(sdJwtVcQuery), [PropertyTarget.REQUEST_OBJECT]) + .withDcqlQuery(sdJwtVcQuery, [PropertyTarget.REQUEST_OBJECT]) .withPresentationVerification(presentationVerificationCallback) .withRevocationVerification(RevocationVerification.NEVER) .withRequestBy(PassBy.VALUE) diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index 2212994f..79a4ab3c 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -2,6 +2,7 @@ import { EventEmitter } from 'events' import { IPresentationDefinition } from '@sphereon/pex' import { Hasher } from '@sphereon/ssi-types' +import { DcqlQuery } from 'dcql' import { PropertyTarget, PropertyTargets } from '../authorization-request' import { PresentationVerificationCallback } from '../authorization-response' @@ -23,7 +24,7 @@ import { import { assignIfAuth, assignIfRequestObject, isTarget, isTargetOrNoTargets } from './Opts' import { RP } from './RP' import { IRPSessionManager } from './types' -import { DcqlQuery } from 'dcql' + export class RPBuilder { requestObjectBy: ObjectBy diff --git a/packages/siop-oid4vp/lib/types/SIOP.types.ts b/packages/siop-oid4vp/lib/types/SIOP.types.ts index 93db8bd2..54ff1b34 100644 --- a/packages/siop-oid4vp/lib/types/SIOP.types.ts +++ b/packages/siop-oid4vp/lib/types/SIOP.types.ts @@ -100,7 +100,7 @@ export interface AuthorizationRequestPayloadVD12OID4VPD20 presentation_definition_uri?: string client_id_scheme?: ClientIdSchemeOID4VPD20 response_uri?: string // New since OID4VP18 OPTIONAL. The Response URI to which the Wallet MUST send the Authorization Response using an HTTPS POST request as defined by the Response Mode direct_post. The Response URI receives all Authorization Response parameters as defined by the respective Response Type. When the response_uri parameter is present, the redirect_uri Authorization Request parameter MUST NOT be present. If the redirect_uri Authorization Request parameter is present when the Response Mode is direct_post, the Wallet MUST return an invalid_request Authorization Response error. - dcql_query?: DcqlQuery + dcql_query?: string } export type ClientIdSchemeOID4VPD18 = 'pre-registered' | 'redirect_uri' | 'entity_id' | 'did' From b28b39ef0652d4ce69fed7e7a3c6f6ae1479751e Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 16:20:50 +0100 Subject: [PATCH 47/60] chore: dcql fixes --- packages/siop-oid4vp/lib/rp/RP.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index e529aee8..185fa20f 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -434,8 +434,12 @@ export class RP { state, nonce, verification: mergeVerificationOpts(this._verifyResponseOptions, opts), - presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions, - dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery + ...(opts?.presentationDefinitions && !opts?.dcqlQuery && { + presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions + }), + ...(opts?.dcqlQuery && !opts?.presentationDefinitions && { + dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery + }) } } From 6e4e2ccb6cdf2f39e5b761b4b4ca4855dbfe2927 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 16:22:43 +0100 Subject: [PATCH 48/60] chore: dcql fixes --- packages/siop-oid4vp/lib/rp/RP.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/rp/RP.ts b/packages/siop-oid4vp/lib/rp/RP.ts index 185fa20f..e1faec4f 100644 --- a/packages/siop-oid4vp/lib/rp/RP.ts +++ b/packages/siop-oid4vp/lib/rp/RP.ts @@ -437,7 +437,8 @@ export class RP { ...(opts?.presentationDefinitions && !opts?.dcqlQuery && { presentationDefinitions: this._verifyResponseOptions.presentationDefinitions ?? opts?.presentationDefinitions }), - ...(opts?.dcqlQuery && !opts?.presentationDefinitions && { + ...(opts?.dcqlQuery /*&& !opts?.presentationDefinitions */&& { // FIXME presentationDefinitions will be there until we fix the OID4VC-DEMO, it wants a PD purpose field for the screens + dcqlQuery: this._verifyResponseOptions.dcqlQuery ?? opts?.dcqlQuery }) } From 7c0b5e131a83a27e8c160e983eac4cf492333ba9 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 17:07:09 +0100 Subject: [PATCH 49/60] chore: lockfile --- pnpm-lock.yaml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a90f84f8..2fecd8fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -806,14 +806,12 @@ packages: '@babel/plugin-proposal-async-generator-functions@7.20.7': resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead. peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-proposal-class-properties@7.18.6': resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. peerDependencies: '@babel/core': ^7.0.0-0 @@ -832,35 +830,30 @@ packages: '@babel/plugin-proposal-export-namespace-from@7.18.9': resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead. peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-proposal-object-rest-spread@7.20.7': resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead. peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-proposal-optional-catch-binding@7.18.6': resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead. peerDependencies: '@babel/core': ^7.0.0-0 '@babel/plugin-proposal-optional-chaining@7.21.0': resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. peerDependencies: '@babel/core': ^7.0.0-0 @@ -1982,7 +1975,6 @@ packages: '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -1990,7 +1982,6 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead '@hutson/parse-repository-url@3.0.2': resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} @@ -2237,7 +2228,6 @@ packages: '@npmcli/move-file@1.1.2': resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} engines: {node: '>=10'} - deprecated: This functionality has been moved to @npmcli/fs '@npmcli/name-from-folder@2.0.0': resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} @@ -3021,7 +3011,6 @@ packages: '@xmldom/xmldom@0.7.13': resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} engines: {node: '>=10.0.0'} - deprecated: this version is no longer supported, please update to at least 0.8.* '@xmldom/xmldom@0.8.10': resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} @@ -3177,7 +3166,6 @@ packages: are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} - deprecated: This package is no longer supported. arg@4.1.0: resolution: {integrity: sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==} @@ -3437,7 +3425,6 @@ packages: boolean@3.2.0: resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} - deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. bplist-creator@0.1.0: resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} @@ -4465,7 +4452,6 @@ packages: eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true esm@3.2.25: @@ -4858,7 +4844,6 @@ packages: gauge@3.0.2: resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} engines: {node: '>=10'} - deprecated: This package is no longer supported. gensequence@5.0.2: resolution: {integrity: sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA==} @@ -4969,20 +4954,16 @@ packages: glob@6.0.4: resolution: {integrity: sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==} - deprecated: Glob versions prior to v9 are no longer supported glob@7.1.6: resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} - deprecated: Glob versions prior to v9 are no longer supported glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported glob@9.3.5: resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} @@ -5225,7 +5206,6 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -6408,7 +6388,6 @@ packages: multibase@4.0.6: resolution: {integrity: sha512-x23pDe5+svdLz/k5JPGCVdfn7Q5mZVMBETiC+ORfO+sor9Sgs0smJzAjfTbM5tckeCqnaUuMYoz+k3RXMmJClQ==} engines: {node: '>=12.0.0', npm: '>=6.0.0'} - deprecated: This module has been superseded by the multiformats module multiformats@12.1.3: resolution: {integrity: sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==} @@ -6604,7 +6583,6 @@ packages: npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} @@ -6746,7 +6724,6 @@ packages: osenv@0.1.5: resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} - deprecated: This package is no longer supported. p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} @@ -7408,22 +7385,18 @@ packages: rimraf@2.2.8: resolution: {integrity: sha512-R5KMKHnPAQaZMqLOsyuyUmcIjSeDm+73eoqQpaXA7AZ22BL+6C+1mcUscgOsNd8WVlJuvlgAPsegcx7pjlV0Dg==} - deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@2.4.5: resolution: {integrity: sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==} - deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@4.4.1: @@ -7857,7 +7830,6 @@ packages: superagent@8.1.2: resolution: {integrity: sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==} engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net supertest@6.3.4: resolution: {integrity: sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==} @@ -8240,7 +8212,6 @@ packages: uglify-es@3.3.9: resolution: {integrity: sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==} engines: {node: '>=0.8.0'} - deprecated: support for ECMAScript is superseded by `uglify-js` as of v3.13.0 hasBin: true uglify-js@3.19.3: @@ -8373,7 +8344,6 @@ packages: uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. hasBin: true uuid@7.0.3: From 0ea01253cb806bee270bb250bb2720ea964e19c8 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 13 Jan 2025 17:28:41 +0100 Subject: [PATCH 50/60] chore: force pnpm version --- .github/workflows/build-test-on-pr.yml | 2 +- .github/workflows/build-test-publish-on-push.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-on-pr.yml b/.github/workflows/build-test-on-pr.yml index fde1e54f..5bfb7892 100644 --- a/.github/workflows/build-test-on-pr.yml +++ b/.github/workflows/build-test-on-pr.yml @@ -25,7 +25,7 @@ jobs: node-version: '20.x' - uses: pnpm/action-setup@v4 with: - version: 9 + version: 9.15.3 - run: pnpm install - run: pnpm build - name: run CI tests diff --git a/.github/workflows/build-test-publish-on-push.yml b/.github/workflows/build-test-publish-on-push.yml index 450a530a..5ee72570 100644 --- a/.github/workflows/build-test-publish-on-push.yml +++ b/.github/workflows/build-test-publish-on-push.yml @@ -39,7 +39,7 @@ jobs: node-version: '20.x' - uses: pnpm/action-setup@v4 with: - version: 9 + version: 9.15.3 - run: pnpm install - run: pnpm build - name: run integration tests From 1ac490756b20acb3deb6652cb0ccdbbd1718644a Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 14 Jan 2025 09:43:21 +0100 Subject: [PATCH 51/60] chore: withDcqlQuery update --- packages/siop-oid4vp/lib/rp/RPBuilder.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index 79a4ab3c..84761720 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -228,22 +228,28 @@ export class RPBuilder { return this } - withDcqlQuery(dcqlQuery: DcqlQuery, targets?: PropertyTargets): RPBuilder { + withDcqlQuery(dcqlQuery: DcqlQuery | string, targets?: PropertyTargets): RPBuilder { if (this.getSupportedRequestVersion() >= SupportedVersion.SIOPv2_D12_OID4VP_D20) { this._authorizationRequestPayload.dcql_query = assignIfAuth( { - propertyValue: dcqlQuery, + propertyValue: typeof dcqlQuery === 'string' ? dcqlQuery : JSON.stringify(dcqlQuery), targets }, false ) this._requestObjectPayload.dcql_query = assignIfRequestObject( { - propertyValue: dcqlQuery, + propertyValue: typeof dcqlQuery === 'string' ? dcqlQuery : JSON.stringify(dcqlQuery), targets }, true ) + + // FIXME we need to find a way in the config to select dcql vs PD without breaking OID4VC-DEMO + this._authorizationRequestPayload.presentation_definition = undefined; + this._authorizationRequestPayload.presentation_definition_uri = undefined; + this._requestObjectPayload.presentation_definition = undefined; + this._requestObjectPayload.presentation_definition_uri = undefined; } return this } From 05d39b711781d495d7472d71101a038d6eefc793 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 14 Jan 2025 11:15:06 +0100 Subject: [PATCH 52/60] refactor: Allowed only presentation definition objects. --- packages/siop-oid4vp/lib/authorization-request/Payload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index 07290006..8d8d47e0 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -26,7 +26,7 @@ export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadO return undefined } - if (opts.vp_token.presentation_definition || opts.vp_token.presentation_definition_uri) { + if (opts.vp_token.presentation_definition !== undefined && opts.vp_token.presentation_definition !== null) { const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) if (discoveryResult.error) { throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) From ec6a13e146adbc40dd1ed3dac7c3249329742860 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 14 Jan 2025 11:43:18 +0100 Subject: [PATCH 53/60] refactor: Moved Dcql.ts functions into a Dcql class and made them static. --- .../AuthorizationRequest.ts | 6 +- .../lib/authorization-request/URI.ts | 4 +- .../AuthorizationResponse.ts | 4 +- .../lib/authorization-response/Dcql.ts | 96 +++++++++++-------- .../lib/authorization-response/OpenID4VP.ts | 4 +- 5 files changed, 65 insertions(+), 49 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts index cc27b403..e7e1c0dc 100644 --- a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts +++ b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts @@ -2,7 +2,7 @@ import { parseJWT } from '@sphereon/oid4vc-common' import { DcqlQuery } from 'dcql' import { PresentationDefinitionWithLocation } from '../authorization-response' -import { findValidDcqlQuery } from '../authorization-response' +import { Dcql } from '../authorization-response' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { fetchByReferenceOrUseByValue, removeNullUndefined } from '../helpers' import { authorizationRequestVersionDiscovery } from '../helpers/SIOPSpecVersion' @@ -206,7 +206,7 @@ export class AuthorizationRequest { await this.getSupportedVersion(), ) - const dcqlQuery = await findValidDcqlQuery(mergedPayload) + const dcqlQuery = await Dcql.findValidDcqlQuery(mergedPayload) return { jwt, @@ -291,6 +291,6 @@ export class AuthorizationRequest { } public async getDcqlQuery(): Promise { - return await findValidDcqlQuery(await this.mergedPayloads()) + return await Dcql.findValidDcqlQuery(await this.mergedPayloads()) } } diff --git a/packages/siop-oid4vp/lib/authorization-request/URI.ts b/packages/siop-oid4vp/lib/authorization-request/URI.ts index f6bf42bc..1796b756 100644 --- a/packages/siop-oid4vp/lib/authorization-request/URI.ts +++ b/packages/siop-oid4vp/lib/authorization-request/URI.ts @@ -1,6 +1,6 @@ import { parseJWT } from '@sphereon/oid4vc-common' -import { findValidDcqlQuery } from '../authorization-response/Dcql' +import { Dcql } from '../authorization-response' import { PresentationExchange } from '../authorization-response/PresentationExchange' import { decodeUriAsJson, encodeJsonAsURI, fetchByReferenceOrUseByValue } from '../helpers' import { assertValidRequestObjectPayload, RequestObject } from '../request-object' @@ -166,7 +166,7 @@ export class URI implements AuthorizationRequestURI { if (requestObjectPayload) { // Only used to validate if the request object contains presentation definition(s) | a dcql query await PresentationExchange.findValidPresentationDefinitions({ ...authorizationRequestPayload, ...requestObjectPayload }) - await findValidDcqlQuery({ ...authorizationRequestPayload, ...requestObjectPayload }) + await Dcql.findValidDcqlQuery({ ...authorizationRequestPayload, ...requestObjectPayload }) assertValidRequestObjectPayload(requestObjectPayload) if (requestObjectPayload.registration) { diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 9bb0dcf4..78e7e301 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -6,7 +6,7 @@ import { assertValidVerifyAuthorizationRequestOpts } from '../authorization-requ import { IDToken } from '../id-token' import { AuthorizationResponsePayload, ResponseType, SIOPErrors, VerifiedAuthorizationRequest, VerifiedAuthorizationResponse } from '../types' -import { assertValidDcqlPresentationResult } from './Dcql' +import { Dcql } from './Dcql' import { assertValidVerifiablePresentations, extractNonceFromWrappedVerifiablePresentation, @@ -145,7 +145,7 @@ export class AuthorizationResponse { }, }) } else if (verifiedAuthorizationRequest.dcqlQuery) { - assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, verifiedAuthorizationRequest.dcqlQuery, { + await Dcql.assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, verifiedAuthorizationRequest.dcqlQuery, { hasher: verifyOpts.hasher, }) } else { diff --git a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts index 7740fdb3..f051fae0 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Dcql.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Dcql.ts @@ -13,50 +13,66 @@ import { extractDcqlPresentationFromDcqlVpToken } from './OpenID4VP' * @param authorizationRequestPayload object that can have a dcql_query inside * @param version */ -export const findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise => { - const dcqlQuery: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query').map((d) => d.value) - const definitions = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition') - const definitionsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition[*]') - const definitionRefs = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri') - const definitionRefsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri[*]') - - const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) - const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) - const hasDcql = dcqlQuery && dcqlQuery.length > 0 - - if ([hasPD, hasPdRef, hasDcql].filter(Boolean).length > 1) { - throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) - } - if (dcqlQuery.length === 0) return undefined +export class Dcql { + + static findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise => { + const dcqlQuery: string[] = extractDataFromPath(authorizationRequestPayload, '$.dcql_query').map((d) => d.value) + const definitions = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition') + const definitionsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition[*]') + const definitionRefs = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri') + const definitionRefsFromList = extractDataFromPath(authorizationRequestPayload, '$.presentation_definition_uri[*]') + + const hasPD = (definitions && definitions.length > 0) || (definitionsFromList && definitionsFromList.length > 0) + const hasPdRef = (definitionRefs && definitionRefs.length > 0) || (definitionRefsFromList && definitionRefsFromList.length > 0) + const hasDcql = dcqlQuery && dcqlQuery.length > 0 + + if ([hasPD, hasPdRef, hasDcql].filter(Boolean).length > 1) { + throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_NON_EXCLUSIVE) + } + + if (dcqlQuery.length === 0) return undefined - if (dcqlQuery.length > 1) { - throw new Error('Found multiple dcql_query in vp_token. Only one is allowed') + if (dcqlQuery.length > 1) { + throw new Error('Found multiple dcql_query in vp_token. Only one is allowed') + } + + return DcqlQuery.parse(JSON.parse(dcqlQuery[0])) } - return DcqlQuery.parse(JSON.parse(dcqlQuery[0])) -} + static getDcqlPresentationResult = (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { + hasher?: Hasher + }) => { + const dcqlPresentation = Object.fromEntries( + Object.entries(extractDcqlPresentationFromDcqlVpToken(record, opts)).map(([queryId, p]) => { + if (p.format === 'mso_mdoc') { + return [ + queryId, + { + credential_format: 'mso_mdoc', + doctype: p.vcs[0].credential.toJson().docType, + namespaces: p.vcs[0].decoded + } satisfies DcqlMdocCredential, + ] + } else if (p.format === 'vc+sd-jwt') { + return [queryId, { + credential_format: 'vc+sd-jwt', + vct: p.vcs[0].decoded.vct, + claims: p.vcs[0].decoded + } satisfies DcqlSdJwtVcCredential] + } else { + throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') + } + }), + ) -export const getDcqlPresentationResult = (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { - const dcqlPresentation = Object.fromEntries( - Object.entries(extractDcqlPresentationFromDcqlVpToken(record, opts)).map(([queryId, p]) => { - if (p.format === 'mso_mdoc') { - return [ - queryId, - { credential_format: 'mso_mdoc', doctype: p.vcs[0].credential.toJson().docType, namespaces: p.vcs[0].decoded } satisfies DcqlMdocCredential, - ] - } else if (p.format === 'vc+sd-jwt') { - return [queryId, { credential_format: 'vc+sd-jwt', vct: p.vcs[0].decoded.vct, claims: p.vcs[0].decoded } satisfies DcqlSdJwtVcCredential] - } else { - throw new Error('DcqlPresentation atm only supports mso_mdoc and vc+sd-jwt') - } - }), - ) - - return DcqlPresentationResult.fromDcqlPresentation(dcqlPresentation, { dcqlQuery }) -} + return DcqlPresentationResult.fromDcqlPresentation(dcqlPresentation, { dcqlQuery }) + } -export const assertValidDcqlPresentationResult = async (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }) => { - const result = getDcqlPresentationResult(record, dcqlQuery, opts) - return DcqlPresentationResult.validate(result) + static assertValidDcqlPresentationResult = async (record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { + hasher?: Hasher + }) => { + const result = Dcql.getDcqlPresentationResult(record, dcqlQuery, opts) + return DcqlPresentationResult.validate(result) + } } diff --git a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts index 90400b3d..607d647e 100644 --- a/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts +++ b/packages/siop-oid4vp/lib/authorization-response/OpenID4VP.ts @@ -25,7 +25,7 @@ import { } from '../types' import { AuthorizationResponse } from './AuthorizationResponse' -import { assertValidDcqlPresentationResult } from './Dcql' +import { Dcql } from './Dcql' import { PresentationExchange } from './PresentationExchange' import { AuthorizationResponseOpts, @@ -96,7 +96,7 @@ export const verifyPresentations = async ( ), ) - assertValidDcqlPresentationResult(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) + await Dcql.assertValidDcqlPresentationResult(authorizationResponse.payload.vp_token as string, dcqlQuery, { hasher: verifyOpts.hasher }) if (verifiedPresentations.some((verified) => !verified)) { const message = verifiedPresentations From d8fdf44de4b398a2b23a977fa4f1313251183d77 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 14 Jan 2025 14:19:27 +0100 Subject: [PATCH 54/60] refactor: Removed potentially nulls from removeNullUndefined(...) function --- packages/siop-oid4vp/lib/request-object/Payload.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/siop-oid4vp/lib/request-object/Payload.ts b/packages/siop-oid4vp/lib/request-object/Payload.ts index 18ea2d67..395b6c63 100644 --- a/packages/siop-oid4vp/lib/request-object/Payload.ts +++ b/packages/siop-oid4vp/lib/request-object/Payload.ts @@ -47,9 +47,9 @@ export const createRequestObjectPayload = async (opts: CreateAuthorizationReques state, ...registration.payload, claims, - presentation_definition_uri: payload.presentation_definition_uri, - presentation_definition: payload.presentation_definition, - dcql_query: payload.dcql_query, + ...(payload.presentation_definition_uri && { presentation_definition_uri: payload.presentation_definition_uri }), + ...(payload.presentation_definition && { presentation_definition: payload.presentation_definition }), + ...(payload.dcql_query && { dcql_query: payload.dcql_query }), client_metadata: payload.client_metadata, iat, nbf, From 5510c53152e1166b9301ff7fe310e05cad9399a8 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 20 Jan 2025 17:05:07 +0100 Subject: [PATCH 55/60] chore: PR feedback fixes --- .../lib/__tests__/AuthenticationResponse.response.spec.ts | 2 +- packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts | 2 +- packages/siop-oid4vp/lib/authorization-request/Payload.ts | 2 +- .../lib/authorization-response/AuthorizationResponse.ts | 2 +- .../siop-oid4vp/lib/authorization-response/Payload.ts | 4 ++-- packages/siop-oid4vp/lib/authorization-response/types.ts | 4 ++-- packages/siop-oid4vp/lib/op/OP.ts | 8 ++++---- packages/siop-oid4vp/lib/rp/RPBuilder.ts | 2 +- .../lib/schemas/AuthorizationResponseOpts.schema.ts | 6 +++--- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index 368ff707..aca7be46 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -776,7 +776,7 @@ describe('create JWT from Request JWT should', () => { alg: SigningAlgo.ES256K, }), jwtIssuer: { method: 'did', didUrl: `${mockResEntity.did}#controller`, alg: SigningAlgo.ES256K }, - dcqlQuery: { + dcqlResponse: { dcqlPresentation }, responseMode: ResponseMode.DIRECT_POST, diff --git a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts index 1c504b52..19fa4dcf 100644 --- a/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/SdJwt.spec.ts @@ -520,7 +520,7 @@ describe.skip('RP and OP interaction should', () => { } const authenticationResponseWithJWT = await op.createAuthorizationResponse(verifiedAuthReqWithJWT, { - dcqlQuery: { dcqlPresentation }, + dcqlResponse: { dcqlPresentation }, }) expect(authenticationResponseWithJWT.response.payload).toBeDefined() expect(authenticationResponseWithJWT.response.idToken).toBeDefined() diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index 8d8d47e0..5c572ad2 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -26,7 +26,7 @@ export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadO return undefined } - if (opts.vp_token.presentation_definition !== undefined && opts.vp_token.presentation_definition !== null) { + if (!opts.vp_token.presentation_definition && !opts.vp_token.presentation_definition_uri) { const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) if (discoveryResult.error) { throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) diff --git a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts index 848cea59..b290423e 100644 --- a/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts +++ b/packages/siop-oid4vp/lib/authorization-response/AuthorizationResponse.ts @@ -145,7 +145,7 @@ export class AuthorizationResponse { }, }) } else if (verifiedAuthorizationRequest.dcqlQuery) { - await Dcql.assertValidDcqlPresentationResult(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation, verifiedAuthorizationRequest.dcqlQuery, { + await Dcql.assertValidDcqlPresentationResult(responseOpts.dcqlResponse.dcqlPresentation as DcqlPresentation, verifiedAuthorizationRequest.dcqlQuery, { hasher: verifyOpts.hasher, }) } else { diff --git a/packages/siop-oid4vp/lib/authorization-response/Payload.ts b/packages/siop-oid4vp/lib/authorization-response/Payload.ts index a2bc60b9..2d2f237d 100644 --- a/packages/siop-oid4vp/lib/authorization-response/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-response/Payload.ts @@ -30,8 +30,8 @@ export const createResponsePayload = async ( } // vp tokens - if (responseOpts.dcqlQuery) { - responsePayload.vp_token = DcqlPresentation.encode(responseOpts.dcqlQuery.dcqlPresentation as DcqlPresentation) + if (responseOpts.dcqlResponse) { + responsePayload.vp_token = DcqlPresentation.encode(responseOpts.dcqlResponse.dcqlPresentation as DcqlPresentation) } else { await putPresentationSubmissionInLocation(authorizationRequest, responsePayload, responseOpts, idTokenPayload) } diff --git a/packages/siop-oid4vp/lib/authorization-response/types.ts b/packages/siop-oid4vp/lib/authorization-response/types.ts index 5f8f2b6f..620fc3b3 100644 --- a/packages/siop-oid4vp/lib/authorization-response/types.ts +++ b/packages/siop-oid4vp/lib/authorization-response/types.ts @@ -42,7 +42,7 @@ export interface AuthorizationResponseOpts { tokenType?: string refreshToken?: string presentationExchange?: PresentationExchangeResponseOpts - dcqlQuery?: DcqlQueryResponseOpts + dcqlResponse?: DcqlResponseOpts } export interface PresentationExchangeResponseOpts { @@ -61,7 +61,7 @@ export interface PresentationExchangeResponseOpts { restrictToDIDMethods?: string[] } -export interface DcqlQueryResponseOpts { +export interface DcqlResponseOpts { dcqlPresentation: Record | string> } diff --git a/packages/siop-oid4vp/lib/op/OP.ts b/packages/siop-oid4vp/lib/op/OP.ts index e4fa29fb..cafc2fa4 100644 --- a/packages/siop-oid4vp/lib/op/OP.ts +++ b/packages/siop-oid4vp/lib/op/OP.ts @@ -10,7 +10,7 @@ import { AuthorizationResponse, AuthorizationResponseOpts, AuthorizationResponseWithCorrelationId, - DcqlQueryResponseOpts, + DcqlResponseOpts, PresentationExchangeResponseOpts, } from '../authorization-response' import { encodeJsonAsURI, post } from '../helpers' @@ -107,7 +107,7 @@ export class OP { issuer?: ResponseIss | string verification?: Verification presentationExchange?: PresentationExchangeResponseOpts - dcqlQuery?: DcqlQueryResponseOpts + dcqlResponse?: DcqlResponseOpts }, ): Promise { if ( @@ -296,7 +296,7 @@ export class OP { issuer?: IIssuerId | ResponseIss audience?: string presentationExchange?: PresentationExchangeResponseOpts - dcqlQuery?: DcqlQueryResponseOpts + dcqlResponse?: DcqlResponseOpts }): AuthorizationResponseOpts { const version = opts.version ?? this._createResponseOptions.version let issuer = opts.issuer ?? this._createResponseOptions?.registration?.issuer @@ -311,7 +311,7 @@ export class OP { } // We are taking the whole presentationExchange object from a certain location const presentationExchange = opts.presentationExchange ?? this._createResponseOptions.presentationExchange - const dcqlQuery = opts.dcqlQuery ?? this._createResponseOptions.dcqlQuery + const dcqlQuery = opts.dcqlResponse ?? this._createResponseOptions.dcqlResponse const responseURI = opts.audience ?? this._createResponseOptions.responseURI return { diff --git a/packages/siop-oid4vp/lib/rp/RPBuilder.ts b/packages/siop-oid4vp/lib/rp/RPBuilder.ts index 84761720..ddbb65fd 100644 --- a/packages/siop-oid4vp/lib/rp/RPBuilder.ts +++ b/packages/siop-oid4vp/lib/rp/RPBuilder.ts @@ -245,7 +245,7 @@ export class RPBuilder { true ) - // FIXME we need to find a way in the config to select dcql vs PD without breaking OID4VC-DEMO + // FIXME SPRIND-144 we need to find a way in the config to select dcql vs PD without breaking OID4VC-DEMO this._authorizationRequestPayload.presentation_definition = undefined; this._authorizationRequestPayload.presentation_definition_uri = undefined; this._requestObjectPayload.presentation_definition = undefined; diff --git a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts index 1478d7b7..c16925a4 100644 --- a/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts +++ b/packages/siop-oid4vp/lib/schemas/AuthorizationResponseOpts.schema.ts @@ -53,8 +53,8 @@ export const AuthorizationResponseOptsSchemaObj = { "presentationExchange": { "$ref": "#/definitions/PresentationExchangeResponseOpts" }, - "dcqlQuery": { - "$ref": "#/definitions/DcqlQueryResponseOpts" + "dcqlResponse": { + "$ref": "#/definitions/DcqlResponseOpts" } }, "required": [ @@ -2339,7 +2339,7 @@ export const AuthorizationResponseOptsSchemaObj = { "token_response" ] }, - "DcqlQueryResponseOpts": { + "DcqlResponseOpts": { "type": "object", "properties": { "dcqlPresentation": { From fa56bcc7091d8389f43cce45a114eb1fd87221df Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Mon, 20 Jan 2025 17:06:13 +0100 Subject: [PATCH 56/60] chore: lockfile --- pnpm-lock.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fecd8fd..9991ff9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10022,7 +10022,7 @@ snapshots: '@digitalcredentials/bnid@2.1.2(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1))': dependencies: '@digitalcredentials/base58-universal': 1.0.1 - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) yargs: 15.4.1 transitivePeerDependencies: - react-native @@ -11892,7 +11892,7 @@ snapshots: webcrypto-shim: 0.1.7 optionalDependencies: expo: 48.0.21(@babel/core@7.26.0)(encoding@0.1.13) - react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)) + react-native-securerandom: 1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)) '@sphereon/kmp-mdoc-core@0.2.0-SNAPSHOT.26': dependencies: @@ -18230,7 +18230,7 @@ snapshots: react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) optional: true - react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(encoding@0.1.13)(react@18.3.1)): + react-native-securerandom@1.0.1(react-native@0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1)): dependencies: base64-js: 1.5.1 react-native: 0.71.19(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13)(react@18.3.1) From 2180e7fb420ea71bb1ac56b48fb82d541fde439a Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 21 Jan 2025 10:25:54 +0100 Subject: [PATCH 57/60] chore: reverted definitionVersionDiscovery --- packages/siop-oid4vp/lib/authorization-request/Payload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index 5c572ad2..bd0d4591 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -26,7 +26,7 @@ export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadO return undefined } - if (!opts.vp_token.presentation_definition && !opts.vp_token.presentation_definition_uri) { + if (opts.vp_token.presentation_definition) { const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) if (discoveryResult.error) { throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) From 9069e270188a66267ef329cecf24ea9a00c9f36e Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 21 Jan 2025 11:29:31 +0100 Subject: [PATCH 58/60] chore: added comments in CI --- .github/workflows/build-test-on-pr.yml | 2 +- .github/workflows/build-test-publish-on-push.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-on-pr.yml b/.github/workflows/build-test-on-pr.yml index 5bfb7892..967279a8 100644 --- a/.github/workflows/build-test-on-pr.yml +++ b/.github/workflows/build-test-on-pr.yml @@ -25,7 +25,7 @@ jobs: node-version: '20.x' - uses: pnpm/action-setup@v4 with: - version: 9.15.3 + version: 9.15.3 # TODO remove later, we are temporary dealing with a broken pnpm version in the CI container - run: pnpm install - run: pnpm build - name: run CI tests diff --git a/.github/workflows/build-test-publish-on-push.yml b/.github/workflows/build-test-publish-on-push.yml index 5ee72570..216bcc79 100644 --- a/.github/workflows/build-test-publish-on-push.yml +++ b/.github/workflows/build-test-publish-on-push.yml @@ -39,7 +39,7 @@ jobs: node-version: '20.x' - uses: pnpm/action-setup@v4 with: - version: 9.15.3 + version: 9.15.3 # TODO remove later, we are temporary dealing with a broken pnpm version in the CI container - run: pnpm install - run: pnpm build - name: run integration tests From 19382fa66e9538a9428f797ea7506eaa7da3d263 Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Tue, 21 Jan 2025 11:32:23 +0100 Subject: [PATCH 59/60] chore: removed commented out code --- .../lib/__tests__/AuthenticationResponse.response.spec.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts index aca7be46..381bf698 100644 --- a/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts +++ b/packages/siop-oid4vp/lib/__tests__/AuthenticationResponse.response.spec.ts @@ -465,9 +465,6 @@ describe('create JWT from Request JWT should', () => { } const requestObject = await RequestObject.fromOpts(requestOpts) - /* console.log( - JSON.stringify(await AuthenticationResponse.createJWTFromRequestJWT(requestWithJWT.jwt, responseOpts, verifyOpts)) - );*/ const jwt = await requestObject.toJwt() if (!jwt) throw new Error('JWT is undefined') const authorizationRequest = await AuthorizationResponse.fromRequestObject(jwt, responseOpts, verifyOpts) @@ -783,9 +780,6 @@ describe('create JWT from Request JWT should', () => { } const requestObject = await RequestObject.fromOpts(requestOpts) - /* console.log( - JSON.stringify(await AuthenticationResponse.createJWTFromRequestJWT(requestWithJWT.jwt, responseOpts, verifyOpts)) - );*/ const jwt = await requestObject.toJwt() if (!jwt) throw new Error('JWT is undefined') const authorizationRequest = await AuthorizationResponse.fromRequestObject(jwt, responseOpts, verifyOpts) From 44db1196100f12a14ed742b88102a7125d372aca Mon Sep 17 00:00:00 2001 From: sanderPostma Date: Thu, 23 Jan 2025 10:00:36 +0100 Subject: [PATCH 60/60] chore: fixed definitionVersionDiscovery handling --- .../lib/authorization-request/Payload.ts | 18 +++++++++++------- .../siop-oid4vp/lib/request-object/Payload.ts | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/Payload.ts b/packages/siop-oid4vp/lib/authorization-request/Payload.ts index bd0d4591..1a41ba5d 100644 --- a/packages/siop-oid4vp/lib/authorization-request/Payload.ts +++ b/packages/siop-oid4vp/lib/authorization-request/Payload.ts @@ -1,6 +1,6 @@ import { PEX } from '@sphereon/pex' -import { getNonce, removeNullUndefined } from '../helpers' +import { getNonce, getWithUrl, removeNullUndefined } from '../helpers' import { RequestObject } from '../request-object' import { isTarget, isTargetOrNoTargets } from '../rp/Opts' import { RPRegistrationMetadataPayloadSchema } from '../schemas' @@ -11,13 +11,13 @@ import { PassBy, RPRegistrationMetadataPayload, SIOPErrors, - SupportedVersion, + SupportedVersion } from '../types' import { createRequestRegistration } from './RequestRegistration' import { ClaimPayloadOptsVID1, CreateAuthorizationRequestOpts, PropertyTarget } from './types' -export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadOptsVID1): ClaimPayloadVID1 => { +export const createPresentationDefinitionClaimsProperties = async (opts: ClaimPayloadOptsVID1): Promise => { if ( !opts || !opts.vp_token || @@ -26,10 +26,14 @@ export const createPresentationDefinitionClaimsProperties = (opts: ClaimPayloadO return undefined } - if (opts.vp_token.presentation_definition) { - const discoveryResult = PEX.definitionVersionDiscovery(opts.vp_token.presentation_definition) + let presentationDef = opts.vp_token.presentation_definition + if (!presentationDef && opts.vp_token.presentation_definition_uri) { + presentationDef = await getWithUrl(opts.vp_token.presentation_definition_uri, false) + } + if (presentationDef) { + const discoveryResult = PEX.definitionVersionDiscovery(presentationDef) if (discoveryResult.error) { - throw new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID) + return Promise.reject(new Error(SIOPErrors.REQUEST_CLAIMS_PRESENTATION_DEFINITION_NOT_VALID)) } } @@ -55,7 +59,7 @@ export const createAuthorizationRequestPayload = async ( // TODO: if opts['registration] throw Error to get rid of test code using that key const clientMetadata = opts['registration'] ?? (opts.clientMetadata as ClientMetadataOpts) const registration = await createRequestRegistration(clientMetadata, opts) - const claims = opts.version >= SupportedVersion.SIOPv2_ID1 ? opts.payload.claims : createPresentationDefinitionClaimsProperties(opts.payload.claims) + const claims = opts.version >= SupportedVersion.SIOPv2_ID1 ? opts.payload.claims : await createPresentationDefinitionClaimsProperties(opts.payload.claims) const isRequestTarget = isTargetOrNoTargets(PropertyTarget.AUTHORIZATION_REQUEST, opts.requestObject.targets) const isRequestByValue = opts.requestObject.passBy === PassBy.VALUE diff --git a/packages/siop-oid4vp/lib/request-object/Payload.ts b/packages/siop-oid4vp/lib/request-object/Payload.ts index 395b6c63..408d8575 100644 --- a/packages/siop-oid4vp/lib/request-object/Payload.ts +++ b/packages/siop-oid4vp/lib/request-object/Payload.ts @@ -18,7 +18,7 @@ export const createRequestObjectPayload = async (opts: CreateAuthorizationReques const state = getState(payload.state) const registration = await createRequestRegistration(opts.clientMetadata, opts) - const claims = createPresentationDefinitionClaimsProperties(payload.claims) + const claims = await createPresentationDefinitionClaimsProperties(payload.claims) const metadataKey = opts.version >= SupportedVersion.SIOPv2_D11.valueOf() ? 'client_metadata' : 'registration' const clientId = payload.client_id ?? registration.payload[metadataKey]?.client_id