Your organization needs to accept mobile driver's licenses for identity verification. Some states issue ISO/IEC 18013-5 mdoc credentials, while others are exploring W3C Verifiable Credentials. Building separate verification flows for each format doubles your integration cost and maintenance burden.
This template provides a configuration framework for a verifier that accepts both mdoc and W3C VC credential formats. You'll build one verification endpoint that routes credential validation based on format detection, then applies the appropriate schema validation and trust chain verification for each type.
Purpose of the Template
This configuration template structures a dual-format credential verifier that:
- Detects incoming credential format (CBOR-encoded mdoc vs. JSON-LD VC)
- Routes to format-specific validation logic
- Applies appropriate cryptographic verification for each format
- Maps extracted attributes to your internal identity schema
- Logs verification events with format metadata for compliance reporting
The template is designed for verifying government-issued mobile driver's licenses during account creation or step-up authentication. It's suitable for financial services, healthcare, or regulated industries where you need to support credentials from multiple jurisdictions without building parallel infrastructure.
Prerequisites
Before implementing this configuration:
Technical requirements:
- TLS 1.3 endpoint with certificate pinning for credential presentation
- CBOR parsing library (for mdoc format)
- JSON-LD processor (for VC format)
- Cryptographic verification library supporting ECDSA P-256 and EdDSA
- Certificate path validation for ISO issuer certificates
- DID resolution capability for W3C issuer verification
Trust infrastructure:
- Access to ISO mdoc issuer certificate registry (typically state DMV root certificates)
- DID method resolver configuration (did:web and did:key minimum)
- Revocation checking capability (OCSP for mdoc, status lists for VC)
Schema mapping:
- Internal user record schema with fields for name, date of birth, address, document number
- Attribute mapping rules from ISO 18013-5 namespace and your VC schema vocabulary
Configuration Template
verifier_config:
version: "1.0"
endpoint:
url: "/api/v1/verify-credential"
methods: ["POST"]
tls_version: "1.3"
format_detection:
rules:
- name: "detect_mdoc"
condition: "content_type == 'application/cbor' OR starts_with_cbor_tag"
route_to: "mdoc_validator"
- name: "detect_vc"
condition: "content_type == 'application/vc+ld+json' OR has_json_ld_context"
route_to: "vc_validator"
- name: "reject_unknown"
condition: "default"
action: "return_error"
error_code: "UNSUPPORTED_FORMAT"
mdoc_validator:
enabled: true
issuer_trust:
root_certificates: "/etc/verifier/mdoc-roots/*.pem"
intermediate_certificates: "/etc/verifier/mdoc-intermediates/*.pem"
revocation_check: "ocsp"
ocsp_timeout_ms: 3000
namespace_support:
- "org.iso.18013.5.1"
required_attributes:
- source: "family_name"
target: "user.last_name"
required: true
- source: "given_name"
target: "user.first_name"
required: true
- source: "birth_date"
target: "user.date_of_birth"
required: true
format: "full-date"
- source: "document_number"
target: "user.id_document_number"
required: true
- source: "issue_date"
target: "user.id_issue_date"
required: false
- source: "expiry_date"
target: "user.id_expiry_date"
required: true
validation: "must_be_future"
age_verification:
over_18_check: true
over_21_check: false
selective_disclosure:
respect_holder_selection: true
minimum_attributes: ["family_name", "given_name", "birth_date"]
vc_validator:
enabled: true
issuer_trust:
did_methods: ["did:web", "did:key"]
did_resolver_timeout_ms: 5000
trust_registry: "/etc/verifier/vc-trusted-issuers.json"
context_support:
- "https://www.w3.org/2018/credentials/v1"
- "https://example-state-dmv.gov/credentials/v1"
credential_type:
accepted_types:
- "VerifiableCredential"
- "MobileDriversLicense"
- "IdentityCredential"
required_claims:
- source: "credentialSubject.familyName"
target: "user.last_name"
required: true
- source: "credentialSubject.givenName"
target: "user.first_name"
required: true
- source: "credentialSubject.birthDate"
target: "user.date_of_birth"
required: true
- source: "credentialSubject.licenseNumber"
target: "user.id_document_number"
required: true
- source: "expirationDate"
target: "user.id_expiry_date"
required: true
validation: "must_be_future"
revocation_check:
methods: ["StatusList2021", "RevocationList2020"]
cache_ttl_seconds: 300
proof_verification:
accepted_suites:
- "Ed25519Signature2020"
- "EcdsaSecp256k1Signature2019"
challenge_required: true
challenge_ttl_seconds: 300
attribute_mapping:
transformations:
- field: "date_of_birth"
format: "ISO8601"
- field: "id_expiry_date"
validation: "must_not_be_expired"
derived_attributes:
- name: "age_verified_over_18"
expression: "date_diff(now(), date_of_birth) >= 18 years"
store: true
logging:
events:
- "credential_received"
- "format_detected"
- "validation_started"
- "trust_chain_verified"
- "attributes_extracted"
- "verification_complete"
- "verification_failed"
metadata:
include_format: true
include_issuer_identifier: true
include_timestamp: true
include_error_details: true
retention_days: 90
error_handling:
on_format_detection_failure:
action: "reject"
error_code: "INVALID_CREDENTIAL_FORMAT"
on_trust_verification_failure:
action: "reject"
error_code: "UNTRUSTED_ISSUER"
on_revocation_check_failure:
action: "reject"
error_code: "CREDENTIAL_REVOKED"
on_attribute_extraction_failure:
action: "reject"
error_code: "INCOMPLETE_CREDENTIAL"
on_network_timeout:
action: "fail_open_with_manual_review"
alert: true
Customization Steps
Adjust trust anchors for your jurisdiction:
Replace the root certificate paths and DID trust registry with issuers relevant to your deployment. If you're verifying mDLs from specific U.S. states, you'll need each state DMV's root certificate. For W3C VCs, populate your trust registry with DIDs of authorized issuers.
Map attributes to your schema:
The template maps ISO 18013-5 attributes like family_name and W3C VC claims like credentialSubject.familyName to a generic user.last_name field. Replace user.* targets with your actual database schema fields.
Configure age verification without storing birth dates:
If you need to verify age for regulatory compliance but don't want to store exact birth dates, enable the derived_attributes section. The verifier calculates age at verification time, stores only the boolean result, and discards the birth date.
Set revocation checking timeouts:
OCSP checks for mdoc and status list fetches for VCs can introduce latency. Set timeout_ms values based on your performance requirements. Consider implementing a cache for recently checked revocation statuses.
Define error handling strategy:
The template defaults to strict rejection on trust failures. If you need to support manual review for edge cases (like network timeouts during revocation checks), configure fail_open_with_manual_review and implement an alert workflow.
Validation Steps
After deploying this configuration:
1. Test format detection with sample credentials
Send a test mdoc (CBOR-encoded) and a test VC (JSON-LD) to your endpoint. Verify logs show correct format detection and routing to the appropriate validator.
2. Verify trust chain validation
Use credentials from known issuers in your trust registries. Confirm successful verification. Then test with a credential from an untrusted issuer and verify rejection with UNTRUSTED_ISSUER error code.
3. Validate attribute extraction and mapping
After successful verification, inspect your internal user record. Confirm all required attributes populated correctly and match the source credential values.
4. Test revocation checking
If you have access to a revoked test credential, submit it and verify rejection. Monitor revocation check latency in your logs to ensure timeouts are appropriate.
5. Confirm selective disclosure handling (mdoc)
Submit an mdoc where the holder disclosed only a subset of attributes. Verify your verifier respects the holder's selection and only attempts to extract disclosed attributes.
6. Load test with both formats
Send mixed traffic of mdoc and VC presentations. Monitor CPU and memory usage during CBOR parsing and JSON-LD processing. Adjust worker pool sizes if you see bottlenecks.
7. Review compliance logging
Confirm your audit logs capture format type, issuer identifier, and verification outcome for each transaction. You'll need this metadata for regulatory reporting and incident investigation.
This configuration doesn't solve the broader ecosystem challenge: different jurisdictions will continue adopting different standards based on their regulatory constraints and existing infrastructure. But it offers a practical path to accept credentials from both models without forcing users into a single format or building duplicate verification systems.





