feat(oid4vc): add mDoc credential processor with isomdl-uniffi#11
Open
burdettadam wants to merge 45 commits intomainfrom
Open
feat(oid4vc): add mDoc credential processor with isomdl-uniffi#11burdettadam wants to merge 45 commits intomainfrom
burdettadam wants to merge 45 commits intomainfrom
Conversation
- Refactor mso_mdoc to use isomdl-uniffi for crypto operations - Add key generation and key management routes - Add storage module for keys, certificates, and trust anchors - Add comprehensive unit tests for mDoc functionality - Add isomdl-uniffi dependency (git reference to main branch) - Add Rust toolchain and cache to CI for isomdl-uniffi compilation Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Mock context.inject_or to handle new status_handler code - Update patch from SDJWTIssuer to sd_jwt_sign after implementation change Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Mock profile.session() as proper async context manager - Use patch decorator for jwt_sign and retrieve_or_create_did_jwk - Fix indentation of assertions inside with block Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Fix error class typos: PresVerifeirError -> PresVerifierError, CredVerifeirError -> CredVerifierError - Update storage modules to catch general Exception instead of just InjectionError for graceful error handling - Preserve error messages in credential parsing failures for better debugging - Update GitHub workflow to install uniffi-bindgen for building isomdl-uniffi - Update Docker images to include Rust toolchain for building isomdl-uniffi - Set default ISOMDL_BRANCH to fix/python-build-system in integration tests All 123 mso_mdoc unit tests now passing ✅ Signed-off-by: Adam Burdett <burdettadam@gmail.com>
…for isomdl-uniffi Updated all ISOMDL_BRANCH args in docker-compose.yml from 'main' to 'fix/python-build-system' to ensure integration tests use the fixed build system that works properly in Docker containers. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Added a new integration-tests job that runs after linting-and-unit-tests job completes successfully. The integration tests: - Only run for plugins with an integration/ directory - Use Docker Compose to run end-to-end tests - Build and run test-river service for each changed plugin - Provide detailed logging if tests fail - Clean up containers after each plugin test This ensures that both unit tests and integration tests pass before PRs can be merged. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Add support for credential_identifier parameter (OID4VCI 1.0) - Enforce mutual exclusivity between credential_identifier and format per § 7.2 - Maintain backward compatibility with draft spec format parameter - Return clear error messages for invalid request combinations Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Add token_endpoint to credential issuer metadata for draft spec clients - Fix credentials field in offer to use format (vc+sd-jwt) instead of identifier - Relax JWT proof typ header validation to accept common variants - Maintain full OID4VCI 1.0 compliance while supporting legacy clients Accepts typ values: openid4vci-proof+jwt (1.0), JWT, jwt, openid4vci-jwt (draft) Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- test_oid4vci_10_metadata: verify credential_configuration_ids in metadata - test_oid4vci_10_credential_request_with_identifier: validate credential_identifier usage - test_oid4vci_10_mutual_exclusion: enforce field exclusivity per § 7.2 - test_oid4vci_10_proof_of_possession: validate JWT proof handling All tests verify compliance with OID4VCI 1.0 final specification Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Add openid_configuration to public routes exports - Register /.well-known/openid-configuration route - Enables OAuth 2.0 Authorization Server discovery per RFC 8414 - Required for OID4VCI 1.0 token endpoint discovery Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Register P256 key type for ES256 signature support - Add comprehensive logging to setup and lifecycle events - Reorganize credential processor registration - Move supported_cred_is_unique to utils module for better code organization - Remove circular dependency between oid4vc and jwt_vc_json Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Change Credo agent port to avoid conflicts - Update all test fixtures and URLs to use new port - Update docker-compose port mappings - Ensure consistent port configuration across integration tests Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Specify linux/amd64 platform for consistent builds across architectures - Update base image Dockerfile target and build context - Use isomdl-uniffi main branch instead of fix/python-build-system - Improve build reproducibility and cross-platform compatibility Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Remove isomdl-uniffi from poetry dependencies (causes build issues) - Install via platform-specific pre-built wheels from GitHub releases - Add wheels for macOS (ARM/x86), Linux, and Windows - Resolves Rust compilation requirements and improves install reliability - Update lock files to reflect dependency changes Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Use lazy % formatting in LOGGER calls per pylint rules - Fix unused kwargs parameter with underscore prefix - Replace broad Exception catch with specific TypeError/ValueError - Ensures CI linting checks pass Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- Make isomdl_uniffi imports conditional in mdoc issuer and verifier modules - Add ISOMDL_AVAILABLE flag to check library availability at runtime - Add IsomdlNotAvailableError for clear error messaging when library is missing - Remove Rust toolchain and uniffi-bindgen setup from CI workflow (The uniffi-bindgen crate name was wrong and isomdl-uniffi wheels aren't available on the release yet) - Tests using isomdl_uniffi will skip gracefully when library is not installed Signed-off-by: Adam Burdett <burdettadam@gmail.com>
… Rust setup" This reverts commit 7c0ef5c. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Replace broken Rust toolchain setup with direct wheel installation from the isomdl-uniffi GitHub release. The wheel is only installed when oid4vc plugin is in the changed plugins list. - Removes rust-toolchain setup (no Cargo.toml in repo) - Removes uniffi-bindgen cargo install (wrong package name) - Uses prebuilt manylinux wheel from v0.1.0-test release Signed-off-by: Adam Burdett <burdettadam@gmail.com>
305ae81 to
6a9c292
Compare
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
…ings Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
6317663 to
ccbfb41
Compare
- registration.py: add /.well-known/openid_credential_issuer (underscore)
endpoint alongside the dash variant; OID4VCI 1.0 spec requires the
underscore URL, Credo uses it for metadata discovery, without it all
Credo-based issuance flows fail
- did_utils.py: revert _create_default_did to use wallet.create_local_did()
instead of wallet.create_key() + wallet.store_did(DIDInfo(...)); the
latter fails at runtime in ACA-Py 1.4.0, causing 500 on every
/oid4vp/request call; also drop now-unused imports
- routes/exchange.py: catch VerificationKeyStrategyError from
get_verification_method_id_for_did and return 400 instead of 500;
did:jwk DIDs not resolvable via the default key strategy were
bubbling up as unhandled exceptions
- integration/oid4vci_client/client.py: fix CredentialOffer.from_dict to
accept both the raw offer object and the legacy wrapped form
{"credential_offer": {...}}; also fall back to "credentials" key when
"credential_configuration_ids" is absent for backward compatibility
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
ccbfb41 to
7c1c0fd
Compare
- did_utils.py: pass DID_JWK method object instead of string literal
to create_local_did(); the method parameter requires a DIDMethod
instance, not a str, so the string caused a TypeError that propagated
as an unhandled exception (text/plain 500) from both the token
endpoint and the oid4vp/request endpoint
- exchange.py: handle did:jwk DIDs whose verification method is not
returned by BaseVerificationKeyStrategy (fall back to {did}#0);
also convert bare ValueError raises to HTTPBadRequest so they do not
escape as unhandled 500s
- registration.py: add Deprecation: true header to the deprecated
underscore well-known endpoint (openid_credential_issuer) via a
thin wrapper; the dash variant (openid-credential-issuer) is the
canonical OID4VCI 1.0 endpoint
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
create_local_did(method=DID_JWK) fails with "Error when creating local DID" because ACA-Py does not know how to derive a did:jwk: string from a key for a plugin-registered DID method. Replicate the exact same approach used by the /did/jwk/create admin route: generate the key with aries_askar, insert it into the keystore via session.handle.insert_key, construct the did:jwk: string from the public JWK, create a DIDInfo, and call wallet.store_did. This is guaranteed to produce a DID that jwt_sign / key_material_for_kid can resolve because the key is stored under its JWK thumbprint which is used as verkey. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
…tion headers
For did:jwk DIDs, skip the DefaultVerificationKeyStrategy DID resolution
path entirely. The DID resolver may throw non-VerificationKeyStrategyError
exceptions (e.g., DIDNotFound, ResolutionError) that were propagating as
unhandled 500s. Since the verification method for did:jwk is always
{did}#0, we can safely hardcode this without going through the resolver.
Also adds the missing Warning and Sunset deprecation headers to the
underscore endpoint wrapper, which are required by test_dual_oid4vci_endpoints.
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
OID4VPPresentation.__init__ accepted **kwargs which were passed through to BaseRecord.__init__, but BaseRecord does not accept 'client_id'. This caused a TypeError when vp_request.py passed client_id=jwk.did, resulting in an unhandled 500 from POST /oid4vp/request. Add client_id as an explicit field in the model, store it in record_value for persistence, and add it to the schema for serialization. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- In issuance.ts: format detection was only checking constructor.name, which can be unreliable in compiled/transpiled JS. Now concatenates constructor.name with record.type (already used for storage decisions) so SdJwtVcRecord/MdocRecord/W3cCredentialRecord are always detected correctly regardless of minification. - In registration.py: split Warning header string literal to fix E501 ruff lint error (97 > 90 chars). Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
ACA-Py's key_material_for_kid only handles JsonWebKey2020, Ed25519VerificationKey2018, and Ed25519VerificationKey2020 verification method types. Credo 0.6.x generates did:key documents with the newer Multikey type, which causes 'Invalid kid' 400 errors from ACA-Py. Fix: always use JWK binding in credentialBindingResolver so the proof JWT carries the holder's public key in a 'jwk' header, which ACA-Py verifies directly via Key.from_jwk() without DID resolution. Also fix W3C credential extraction: W3cCredentialRecord does not have credentialInstances[]; instead use record.credential.serializedJwtVc for JWT-encoded W3C credentials. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
… JAR The JAR (JWT Authorization Request) payload had client_id = config.endpoint (an HTTP URL). The @openid4vc library interprets HTTP URL client_ids as OpenID Federation entities and tries to verify the JAR using Federation mechanisms, which Credo does not support, resulting in: 'Unable to verify jws with unsupported jws signer method federation' Fix: set client_id = jwk.did (the did:jwk identifier) in the JAR payload, matching the client_id already present in the request_uri query parameter. Also add client_id_scheme = 'did' so holders use DID-based JAR verification. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
…llision DCQLQuery, OID4VPPresentation, and OID4VPRequest all used RECORD_TYPE='oid4vp'. This caused DCQLQuery.query() to return records of all three types from the Askar store (which indexes by record type/category). When serializing mixed records through DCQLQuerySchema, unexpected exceptions caused HTTP 500 on GET /oid4vp/dcql/queries. Fix: change DCQLQuery.RECORD_TYPE from 'oid4vp' to 'oid4vp-dcql' so that DCQL query records are stored and retrieved in their own category. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
- OID4VPRequest.record_value now includes pres_def_id and dcql_query_id so they are persisted in record storage (not just as tags) and available on retrieve_by_id. Fixes presentation flows where neither presentation_definition nor dcql_query appeared in the JAR payload. - Add 'jwk' to cryptographic_binding_methods_supported for all SD-JWT and JWT VC test configurations so Credo (which always binds via JWK) can successfully bind credentials during issuance. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Root cause: JAR payload included 'scope: vp_token' alongside
'presentation_definition' or 'dcql_query'. The @openid4vc/openid4vp
library validates that EXACTLY ONE of {scope, presentation_definition,
presentation_definition_uri, dcql_query} is present — having two
triggers the '> 1' validation error with message 'Exactly one of the
following parameters MUST be present'.
Also add client_id_scheme=did to the openid:// URI so the holder
library can determine DID-based JAR verification upfront.
Revert JWT VC cryptographic_binding_methods_supported back to ['did']
(JWK binding is only needed for SD-JWT, not JWT VC formats).
Fixes all Credo OID4VP presentation failures.
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Signed-off-by: Adam Burdett <burdettadam@gmail.com>
Credo 0.6.x only maps kmsKeyId onto SdJwtVcRecord credential instances when the credential format is dc+sd-jwt OR when credentialConfiguration.vct is present (FIXME in OpenId4VciHolderService.ts:1230). For vc+sd-jwt credentials issued by ACA-Py without top-level vct in issuer metadata, kmsKeyId stays undefined, causing presentations to use legacyKeyId (= JWK thumbprint) which is not the key id stored in askar. Capture key IDs created in credentialBindingResolver and manually set kmsKeyId on SdJwtVcRecord.credentialInstances before storage. This ensures extractKeyFromHolderBinding uses the correct UUID key ID during presentation. Signed-off-by: Adam Burdett <burdettadam@gmail.com>
0bb2fa1 to
6e5eafa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refactor mso_mdoc to use isomdl-uniffi for crypto operations.
Changes
Dependencies