Skip to content

[WAL-896] feat(wallet): finalize authenticated OpenID4VP presentation flow - #1885

Closed
philpotisk wants to merge 5 commits into
feature/wal-896-verifierfrom
feature/wal-896
Closed

[WAL-896] feat(wallet): finalize authenticated OpenID4VP presentation flow#1885
philpotisk wants to merge 5 commits into
feature/wal-896-verifierfrom
feature/wal-896

Conversation

@philpotisk

@philpotisk philpotisk commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

This is the WAL-896 wallet, protocol, and mobile consumer half, stacked directly on the verifier prerequisite #2055. It is based on feature/wal-896-verifier, which now sits on current main after walt-id/waltid-identity#2031.

The branch makes wallet2/mobile presentation consume authenticated Final Request Objects while preserving the stateless HTTP continuation API and the retained mobile preview flow. The coordinated Enterprise counterpart is walt-id/waltid-identity-enterprise#553.

What Changed

Authenticated wallet2 and mobile flow

  • Requires strict signed Request Object resolution for wallet2/mobile presentation, including the expected audience and wallet-controlled client trust configuration.
  • Re-resolves the immutable signed request URL for preview, build, response, and rejection so caller-supplied request state cannot alter the reviewed transaction.
  • Keeps both continuation models: single-use retained preview state for the mobile consent flow, and stateless preview/build/send/reject operations bound to the same signed request URL.
  • Preserves the wallet2 routes and request-based APIs introduced by Fix/wallet cleanup #1970; this branch wires trust and authenticated resolution through them rather than restoring caller-echoed AuthorizationRequest state.
  • Exposes the negotiated response mode in the mobile presentation request model and refreshes the generated ABI/API snapshot.

DCQL and Crypto2 response handling

  • Enforces DCQL Final semantics, credential-set references, complete disclosure paths, trusted-authority handling, and typed required-credential availability failures.
  • Treats a missing required credential as a protocol-level preview error that can be rejected safely; malformed or unsupported matcher constraints remain fail-closed.
  • Makes Crypto2 response-encryption selection deterministic and binds the selected verifier key and encryption parameters to the authenticated request.

X.509 and mobile fixtures

  • Adds platform-specific X.509 certificate-chain validation needed by the wallet client-identifier path, with explicit trust-result handling and no system-trust fallback.
  • Adds signed Request Object fixtures and Android/iOS mobile coverage for the signed inline URL and Request URI POST contracts.

Stack and ownership

Caveats and Follow-Ups

  • The public-demo mobile checks remain enabled and are not skipped. They require the deployed verifier2 service to emit the signed inline Request Object supplied by [WAL-896] feat(verifier2): expose authenticated request objects #2055; until that deployment is available, those checks can fail before wallet processing begins.
  • Recommended merge/deployment order is explicit: review and deploy the verifier changes in [WAL-896] feat(verifier2): expose authenticated request objects #2055, rerun the public Android/iOS checks against that deployment, then review and merge this wallet/mobile PR. Keeping the two logical changes stacked gives each PR a clean diff while preserving one combined delivery path.
  • Request URI transport still accepts HTTP as well as HTTPS; tightening that repository-wide policy is outside this PR.
  • The legacy waltid-wallet-api presentation implementation is not migrated to this wallet2/mobile Final-validation contract.
  • X.509 client-identifier prefixes require the wallet to provide the intended trust anchors; no system-trust fallback is introduced.

Breaking

  • Signed Request Objects are required by default for wallet2/mobile resolution.
  • Successful mobile preview models now expose the negotiated response mode.
  • This branch does not remove the build-vp-token or send-response route surface preserved from Fix/wallet cleanup #1970; those operations remain bound to the original signed request URL.

@linear-code

linear-code Bot commented Jul 9, 2026

Copy link
Copy Markdown

WAL-896

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4be930d7-4e13-489c-a4a7-83c554f533e4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@philpotisk
philpotisk marked this pull request as ready for review July 13, 2026 14:37
@waltkb
waltkb self-requested a review July 13, 2026 14:38

@waltkb waltkb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The branch contains various OpenID4VP 1.0 Final violations, pre-Final (OpenID4VP Draft) protocol remnants, compilation failures, broken default Issuer2 signing configuration, conformance tooling that can report false success, etc

btw, why is there so much trailing whitespace across the files?

@philpotisk
philpotisk requested review from szijpeter and waltkb July 16, 2026 08:33

@szijpeter szijpeter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of concerns and nitpicks from a (mostly) mobile / wallet perspective. nice work otherwise

Comment thread .github/workflows/gradle-macos.yml Outdated
Comment thread waltid-applications/mobile-e2e-fixtures/ios/TestHelpers/DemoBackend.swift Outdated
Comment thread WAL-896-VALIDATION.md Outdated

@szijpeter szijpeter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvements! 👏🏼

Most of my earlier mobile/wallet concerns are addressed. One blocking issue remains: the Android EHIC integration tests should stay enabled imo. They pass on this PR head and on main, and the public-demo tests do not cover the same POST Request Object retrieval, wallet metadata/nonce, and signed Request Object path.

I’m fine with keeping the iOS EHIC tests skipped until native PKIX/x509_hash validation is supported, but the skip rationale should accurately document that limitation and the trust-anchor follow-up.

My remaining API-compatibility and loopback-HTTPS comments are non-blocking, although I think they would be worth considering.

@waltkb

waltkb commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Also, WalletPresentationHandler.kt (lines ~626-683) accepts a caller-supplied AuthorizationRequest objects for token construction and sending, and /send-response does not do wallet ownership resolution (at Wallet2RouteHandler.kt, roughly lines 758-768). This means that, theoretically, the request could be changed after the /resolve-request step (things like nonce, verifier key, and response URI) -> the fetcher would then be sent to perform an arbitrary outbound POST, and for encrypted mdocs, changing keys between steps will also breaks transcript binding

@waltkb

waltkb commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

In addition, the changed code at WalletPresentFunctionality2.kt (lines ~639-650) should include a call to validateAuthorizationRequest, otherwise a signed request missing nonce reaches consent and later fails through nonce!! instead of being rejected as invalid_request

@philpotisk

Copy link
Copy Markdown
Contributor Author

Regarding #1885 (comment): agreed and contained in 04beebf4a. We removed the /present/build-vp-token and /present/send-response routes together with their caller-controlled request/result models and WalletPresentationHandler methods. A remote caller can no longer resubmit or mutate an AuthorizationRequest, response URI, nonce, response mode, verifier key, or prebuilt VP token between those steps, and the arbitrary outbound POST path is gone. The retained preview/submit flow consumes the wallet-scoped authenticated ResolvedAuthorizationRequest captured during preview. A durable manual-flow follow-up is documented to use an opaque account/wallet-scoped transaction ID, immutable authenticated state, TTL, atomic one-time consumption, and persistent multi-instance storage before an equivalent step API is exposed again.

@philpotisk

Copy link
Copy Markdown
Contributor Author

Regarding #1885 (comment): fixed in 04beebf4a. The isolated request-resolution path now delegates to WalletPresentFunctionality2.resolveAuthorizationRequest, whose common validation rejects a missing or blank nonce. The presentation path also runs PresentationRequestValidator.validate before credential selection and returns invalid_request through a safely bound response channel. resolvedAuthorizationRequestRejectsMissingNonceBeforeCredentialSelection verifies that a pre-resolved request without nonce never reaches consent or credential selection.

@szijpeter
szijpeter dismissed their stale review July 22, 2026 07:33

my earlier concerns were addressed

@szijpeter
szijpeter self-requested a review July 22, 2026 08:07
@szijpeter
szijpeter changed the base branch from main to chore/wal-896-pr-index-refresh July 23, 2026 08:15
@szijpeter
szijpeter changed the base branch from chore/wal-896-pr-index-refresh to main July 23, 2026 08:16
@szijpeter
szijpeter changed the base branch from main to chore/wal-896-pr-link-refresh July 23, 2026 09:10
@szijpeter
szijpeter changed the base branch from chore/wal-896-pr-link-refresh to main July 23, 2026 09:10
@szijpeter
szijpeter changed the base branch from main to chore/wal-896-pr-link-refresh July 23, 2026 11:43
@szijpeter
szijpeter changed the base branch from chore/wal-896-pr-link-refresh to main July 23, 2026 11:43

@szijpeter szijpeter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed a couple of things from the mobile side (test fixtures mostly) and updated the branch from main. I've also refreshed the related enterprise branch and opened a PR for it: https://github.com/walt-id/waltid-identity-enterprise/pull/553

looks good to me from the mobile perspective, but would leave the final word for @waltkb

@szijpeter
szijpeter requested a review from waltkb July 23, 2026 14:41
@szijpeter
szijpeter force-pushed the feature/wal-896-verifier branch from 33b2f8c to 28a6a7c Compare August 7, 2026 14:11
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from 28a6a7c to f6b304d Compare August 13, 2026 10:24
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896 branch 2 times, most recently from 3310994 to 89bcd8f Compare August 13, 2026 11:15
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from f6b304d to ea22deb Compare August 13, 2026 12:16
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from ea22deb to 8296069 Compare August 13, 2026 13:16
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from 8296069 to 437b624 Compare August 20, 2026 08:32
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from 437b624 to d63c3d2 Compare August 20, 2026 15:14
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from d63c3d2 to 38cab45 Compare August 20, 2026 18:26
@JakeFernandes98
JakeFernandes98 force-pushed the feature/wal-896-verifier branch from 38cab45 to 2a32e57 Compare August 20, 2026 19:18
szijpeter and others added 5 commits August 21, 2026 11:40
* feat(verifier2): expose authenticated request objects

* feat(wallet): finalize authenticated OpenID4VP presentation flow
…ches

Keep WAL-896's plain-request RedirectUri gate, but refuse a contradicting
response destination with the same message as Request Object binding.
Android does not inherit jvmMain, so WAL-896's new expect had no actual
and compileAndroidMain failed during assembleDebug.
openid4vp-wallet is JVM-only, so Android loaded OrderedCertificateChain_jvmKt
for platformSupportsPkixCertificatePathValidation. Keep the actual in
jvmCommon so the JVM and Android artifacts expose the same class.
RFC 5280 treats a missing KeyUsage as unrestricted. Requiring
digitalSignature when the extension is absent rejected verifier
attestation JWTs that still sign the request correctly.
@sonarqubecloud

Copy link
Copy Markdown

@JakeFernandes98

Copy link
Copy Markdown
Contributor

Superseded by folding the WAL-896 identity stack into #2091, which now targets main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:mobile Run mobile related CI workflows for this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants