UNPKG

@sphereon/did-auth-siop

Version:

Self Issued OpenID V2 (SIOPv2) and OpenID 4 Verifiable Presentations (OID4VP)

89 lines (76 loc) 3.45 kB
import { Hasher } from '@sphereon/ssi-types' import { DcqlMdocCredential, DcqlPresentation, DcqlPresentationResult, DcqlQuery, DcqlSdJwtVcCredential } from 'dcql' import { extractDataFromPath } from '../helpers' import { AuthorizationRequestPayload, SIOPErrors } from '../types' import { extractDcqlPresentationFromDcqlVpToken } from './OpenID4VP' /** * 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 class Dcql { static findValidDcqlQuery = async (authorizationRequestPayload: AuthorizationRequestPayload): Promise<DcqlQuery | undefined> => { 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') } 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') } }), ) return DcqlPresentationResult.fromDcqlPresentation(dcqlPresentation, { dcqlQuery }) } static assertValidDcqlPresentationResult = async ( record: DcqlPresentation | string, dcqlQuery: DcqlQuery, opts: { hasher?: Hasher }, ) => { const result = Dcql.getDcqlPresentationResult(record, dcqlQuery, opts) return DcqlPresentationResult.validate(result) } }