Skip to content

Inji Verfiy - same device web-wallet return drops the response_code #2037

@RanvSing

Description

@RanvSing

Inji Verify — same-device Web-Wallet return drops the response_code (result card never renders)

Date: 2026-06-11
Components: inji-verify UI + @injistack/react-inji-verify-sdk (verifier side)
Images: inji-verify-ui:0.18.1, inji-verify-service:0.18.1
Wallet: inji-web (Mimoto BFF) — same-device Web-Wallet flow

TL;DR

In the same-device Web Wallets flow, the credential is presented successfully and the
verifier returns the browser to its own origin with a valid response_code in the URL
fragment
— but the verify-UI never consumes it. The user lands on the verifier home page
instead of the result card. The wallet and the verifier backend are both correct; the bug
is in the verifier UI's return handling.

Environment / setup

  • Verifier client_id_scheme = did; signed (request_uri) authorization requests.
  • Wallet registered as a Web Wallet (walletBaseUrl = http://localhost:3004).
  • DB note: verify.vp_submission must have the response_code, response_code_expiry_at,
    response_code_used columns. The 0.18.1 service entity expects them but the bundled db-init
    did not create them — add them or the response_code path 500s before you ever reach this UI bug.

Steps to reproduce

  1. Start a verification, choose Web Wallets → inji-web, Proceed.
  2. The SDK navigates the same tab to http://localhost:3004/authorize?client_id=…&request_uri=….
  3. Present the credential in inji-web and confirm.
  4. inji-web POSTs the VP (direct_post) and follows the verifier's returned redirect back.
  5. Browser lands on https://<verifier>/#response_code=<uuid>.

Expected: verify-UI reads the response_code, fetches the VP result, renders the result card.
Actual: verify-UI shows the home page; the result card never appears.

Evidence (this is the important part)

1. The verifier's own signed request uses direct_post with no redirect_uri (correct for
direct_post — the browser-return URL is delivered in the direct-post response):

response_type : vp_token
response_mode : direct_post
response_uri  : https://<verifier>/v1/verify/vp-submission/direct-post
redirect_uri  : <absent>
state         : req_d45e9c19-…
nonce         : <present>

2. The browser's final URL after presenting (captured from the address bar):

https://<verifier>/#response_code=da5d05f8-9771-4382-908d-ecaad108c716

→ the wallet honored direct_post, the verifier replied with a redirect_uri carrying
#response_code=…, and the wallet navigated the browser back. The round-trip works.

3. The verifier stored the response_code but it was never used:

SELECT response_code, response_code_used FROM verify.vp_submission
 WHERE response_code='da5d05f8-9771-4382-908d-ecaad108c716';
-- da5d05f8-…  |  response_code_used = f   ← never consumed

Root cause (verifier UI)

The response_code comes back in the URL fragment (window.location.hash), but the UI's
cold-return resume logic looks in the query string. In
verify-ui/src/components/Home/VerificationSection/VpVerification.tsx:

const searchParams = new URLSearchParams(window.location.search); // <-- .search (query)
if (searchParams.has("response_code")) return;

The SDK (inji-verify-sdk/.../OpenID4VPVerification.tsx) does read the fragment correctly:

const params = new URLSearchParams(window.location.hash.substring(1)); // <-- .hash
const responseCode = params.get("response_code");
if (responseCode) { isActiveRef.current = true; fetchVPResult(responseCode); }

…but on a cold load of / after the bounce, the app renders Home and the
OpenID4VPVerification component is not mounted (redux flow state is reset; DisplayActiveStep
falls through to <></>), so that fragment handler never runs. Net effect: the fragment
response_code is seen by nobody, and response_code_used stays false.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions