npm.io
0.2.0 • Published 7 months ago

@verifiables/request-converter

Licence
Apache-2.0
Version
0.2.0
Deps
0
Size
97 kB
Vulns
0
Weekly
0

Presentation Definition & DCQL to mDoc DeviceRequest Converter

A TypeScript library for converting DIF Presentation Exchange Presentation Definitions and DCQL (Digital Credentials Query Language) queries to ISO 18013-5 mDoc DeviceRequest structures.

Overview

This library bridges important standards in the digital identity space:

  • DIF Presentation Exchange v2.x: A specification that defines how Verifiers can express proof requirements and how Holders can describe proof submissions.
  • DCQL (Digital Credentials Query Language): The new query language defined in OpenID4VP for requesting verifiable credentials in a more flexible way.
  • ISO 18013-5 (mDL): The international standard for mobile driver's licenses, which defines the DeviceRequest structure for requesting credential data.

The converter is particularly useful for:

  • OpenID4VP implementations that use Presentation Exchange or DCQL with mDoc credentials
  • EUDI Wallet ecosystem implementations
  • Any system bridging W3C/DIF/OpenID standards with ISO 18013-5 mDoc credentials

Installation

npm install @verifiables/request-converter

Or with your preferred package manager:

yarn add @verifiables/request-converter
pnpm add @verifiables/request-converter

Quick Start

DCQL Query Conversion
import { convertDcqlQueryToDeviceRequest } from '@verifiables/request-converter';

// DCQL query (as used in OpenID4VP)
const dcqlQuery = {
  credentials: [{
    id: 'my_mdl',
    format: 'mso_mdoc',
    meta: { doctype_value: 'org.iso.18013.5.1.mDL' },
    claims: [
      { path: ['org.iso.18013.5.1', 'family_name'], intent_to_retain: false },
      { path: ['org.iso.18013.5.1', 'given_name'], intent_to_retain: false },
    ]
  }]
};

const result = convertDcqlQueryToDeviceRequest(dcqlQuery);
console.log(result.deviceRequest);
// {
//   version: "1.0",
//   docRequests: [{
//     itemsRequest: {
//       docType: "org.iso.18013.5.1.mDL",
//       nameSpaces: {
//         "org.iso.18013.5.1": {
//           family_name: false,
//           given_name: false
//         }
//       }
//     }
//   }]
// }
Presentation Definition Conversion
import { convertPresentationDefinitionToDeviceRequest } from '@verifiables/request-converter';

const presentationDefinition = {
  id: "mDL-request",
  input_descriptors: [{
    id: "org.iso.18013.5.1.mDL",
    format: { mso_mdoc: { alg: ["ES256"] } },
    constraints: {
      limit_disclosure: "required",
      fields: [
        { path: ["$['org.iso.18013.5.1']['family_name']"], intent_to_retain: false },
        { path: ["$['org.iso.18013.5.1']['given_name']"], intent_to_retain: false }
      ]
    }
  }]
};

const result = convertPresentationDefinitionToDeviceRequest(presentationDefinition);
Auto-detect Input Type
import { convertToDeviceRequest } from '@verifiables/request-converter';

// Works with both DCQL and Presentation Definition
const result = convertToDeviceRequest(input); // Auto-detects input type

API Reference

DCQL Conversion
convertDcqlQueryToDeviceRequest(dcqlQuery, options?)

Converts a DCQL query to a DeviceRequest.

Parameters:

  • dcqlQuery: The DCQL query object with credentials array
  • options (optional): Conversion options
    • version: DeviceRequest version string (default: "1.0")
    • defaultIntentToRetain: Default intent_to_retain value if not specified (default: false)
    • mdocOnly: Only process mso_mdoc format credentials (default: true)
    • validate: Whether to validate input (default: true)
Presentation Definition Conversion
convertPresentationDefinitionToDeviceRequest(presentationDefinition, options?)

Converts a Presentation Definition to a DeviceRequest.

Parameters:

  • presentationDefinition: The DIF Presentation Exchange Presentation Definition
  • options (optional): Conversion options (same as above)
Unified Conversion
convertToDeviceRequest(input, options?)

Auto-detects input type and converts to DeviceRequest.

Utility Functions
createDeviceRequest(docType, elements, version?)

Creates a DeviceRequest directly from docType and elements.

const deviceRequest = createDeviceRequest(
  'org.iso.18013.5.1.mDL',
  [
    { namespace: 'org.iso.18013.5.1', element: 'family_name', intentToRetain: false },
    { namespace: 'org.iso.18013.5.1', element: 'given_name', intentToRetain: false },
  ]
);
createDcqlQueryFromDeviceRequest(deviceRequest, options?)

Reverse conversion: creates a DCQL query from a DeviceRequest.

const dcqlQuery = createDcqlQueryFromDeviceRequest(deviceRequest);
createPresentationDefinitionFromDeviceRequest(deviceRequest, options?)

Reverse conversion: creates a Presentation Definition from a DeviceRequest.

Interoperability Functions
convertDcqlCredentialQueryToInputDescriptor(credentialQuery)

Converts a single DCQL credential query to a Presentation Definition input descriptor.

convertInputDescriptorToDcqlCredentialQuery(inputDescriptor)

Converts a Presentation Definition input descriptor to a DCQL credential query.

Validation
validateDeviceRequest(deviceRequest)

Validates a DeviceRequest structure.

const { valid, errors } = validateDeviceRequest(deviceRequest);

DCQL Path Format

For mDoc credentials, DCQL uses a simple path format:

claims: [
  { path: ['namespace', 'element'], intent_to_retain: boolean }
]

Examples:

  • ['org.iso.18013.5.1', 'family_name']
  • ['eu.europa.ec.eudi.pid.1', 'birth_date']
  • ['org.iso.7367.1', 'vehicle_holder']

Presentation Definition Path Format

Presentation Definitions use JSONPath-style expressions:

$['namespace']['element']

Examples:

  • $['org.iso.18013.5.1']['family_name']
  • $['eu.europa.ec.eudi.pid.1']['nationality']

Supported Document Types

The converter recognizes common mDoc document types:

Document Type Default Namespace
org.iso.18013.5.1.mDL org.iso.18013.5.1
eu.europa.ec.eudi.pid.1 eu.europa.ec.eudi.pid.1
org.iso.7367.1.mVRC org.iso.7367.1

Examples

DCQL: Multiple Credentials
const dcqlQuery = {
  credentials: [
    {
      id: 'pid',
      format: 'mso_mdoc',
      meta: { doctype_value: 'eu.europa.ec.eudi.pid.1' },
      claims: [
        { path: ['eu.europa.ec.eudi.pid.1', 'family_name'] },
        { path: ['eu.europa.ec.eudi.pid.1', 'age_over_18'] },
      ]
    },
    {
      id: 'mdl',
      format: 'mso_mdoc',
      meta: { doctype_value: 'org.iso.18013.5.1.mDL' },
      claims: [
        { path: ['org.iso.18013.5.1', 'driving_privileges'] },
      ]
    }
  ],
  credential_sets: [
    { options: [['pid'], ['pid', 'mdl']], required: true }
  ]
};

const result = convertDcqlQueryToDeviceRequest(dcqlQuery);
// Result contains two docRequests, one for PID and one for mDL
KYC with Data Retention
const kycQuery = {
  credentials: [{
    id: 'kyc',
    format: 'mso_mdoc',
    meta: { doctype_value: 'org.iso.18013.5.1.mDL' },
    claims: [
      { path: ['org.iso.18013.5.1', 'family_name'], intent_to_retain: true },
      { path: ['org.iso.18013.5.1', 'document_number'], intent_to_retain: true },
      { path: ['org.iso.18013.5.1', 'portrait'], intent_to_retain: false }, // Only verify
    ]
  }]
};

Type Definitions

The library exports comprehensive TypeScript types:

import type {
  // DCQL types
  DcqlQuery,
  DcqlCredentialQuery,
  DcqlCredentialMeta,
  DcqlClaimQuery,
  DcqlClaimSetQuery,
  DcqlCredentialSetQuery,

  // Presentation Definition types
  PresentationDefinition,
  InputDescriptor,
  Constraints,
  Field,

  // DeviceRequest types
  DeviceRequest,
  DocRequest,
  ItemsRequest,
  NameSpaces,
  DataElements,

  // Conversion types
  ConversionResult,
  ConversionOptions,
  DcqlConversionOptions,
} from '@verifiables/request-converter';

Integration with Other Libraries

With @animo-id/mdoc

The DeviceRequest output is designed to work directly with @animo-id/mdoc's holder functions:

import { 
  createDeviceResponseForDeviceRequest,
  DataItem
} from '@animo-id/mdoc';
import { 
  convertDcqlQueryToDeviceRequest,
} from '@verifiables/request-converter';


// Convert DCQL query (from OID4VP authorization request) to DeviceRequest
const dcqlQuery = {
  credentials: [{
    id: 'mdl',
    format: 'mso_mdoc',
    meta: { doctype_value: 'org.iso.18013.5.1.mDL' },
    claims: [
      { path: ['org.iso.18013.5.1', 'family_name'], intent_to_retain: false },
      { path: ['org.iso.18013.5.1', 'portrait'], intent_to_retain: false },
    ]
  }]
};

const { deviceRequest } = convertDcqlQueryToDeviceRequest(dcqlQuery);

deviceRequest.docRequests = deviceRequest.docRequests.map((docRequest: any) => {
  docRequest.itemsRequest = DataItem.fromData(docRequest.itemsRequest)
  return docRequest
})

// Use the DeviceRequest directly with @animo-id/mdoc holder
const deviceResponse = await createDeviceResponseForDeviceRequest({
  deviceRequest,
  sessionTranscript, // SessionTranscript bytes,
  issuerSigned, // issuerSigned from mDoc,
  signature, // a signature object including a CoseKey signingKey
}, context); // the mdoc context

// deviceResponse is ready to send back to the verifier
With dcql-ts
import { DcqlQuery } from 'dcql';
import { convertDcqlQueryToDeviceRequest } from '@verifiables/request-converter';

// Parse and validate DCQL query using dcql-ts
const parsedQuery = DcqlQuery.parse(rawQuery);
DcqlQuery.validate(parsedQuery);

// Convert to DeviceRequest
const { deviceRequest } = convertDcqlQueryToDeviceRequest(parsedQuery);

Why Proper intent_to_retain Handling Matters

The intent_to_retain field is crucial for privacy compliance (GDPR, etc.):

  • false: Data is only verified in real-time, not stored
  • true: Verifier intends to retain the data

This library properly extracts intent_to_retain from DCQL claims, unlike simplistic implementations that hardcode it to false.

License

Apache-2.0

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

Keywords