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
- Start a verification, choose Web Wallets → inji-web, Proceed.
- The SDK navigates the same tab to
http://localhost:3004/authorize?client_id=…&request_uri=….
- Present the credential in inji-web and confirm.
- inji-web POSTs the VP (
direct_post) and follows the verifier's returned redirect back.
- 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.
Inji Verify — same-device Web-Wallet return drops the
response_code(result card never renders)Date: 2026-06-11
Components:
inji-verifyUI +@injistack/react-inji-verify-sdk(verifier side)Images:
inji-verify-ui:0.18.1,inji-verify-service:0.18.1Wallet: 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_codein the URLfragment — 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
client_id_scheme = did; signed (request_uri) authorization requests.walletBaseUrl = http://localhost:3004).verify.vp_submissionmust have theresponse_code,response_code_expiry_at,response_code_usedcolumns. The 0.18.1 service entity expects them but the bundled db-initdid not create them — add them or the
response_codepath 500s before you ever reach this UI bug.Steps to reproduce
http://localhost:3004/authorize?client_id=…&request_uri=….direct_post) and follows the verifier's returned redirect back.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_postwith noredirect_uri(correct fordirect_post — the browser-return URL is delivered in the direct-post response):
2. The browser's final URL after presenting (captured from the address bar):
→ 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:
Root cause (verifier UI)
The
response_codecomes back in the URL fragment (window.location.hash), but the UI'scold-return resume logic looks in the query string. In
verify-ui/src/components/Home/VerificationSection/VpVerification.tsx:The SDK (
inji-verify-sdk/.../OpenID4VPVerification.tsx) does read the fragment correctly:…but on a cold load of
/after the bounce, the app renders Home and theOpenID4VPVerificationcomponent is not mounted (redux flow state is reset;DisplayActiveStepfalls through to
<></>), so that fragment handler never runs. Net effect: the fragmentresponse_codeis seen by nobody, andresponse_code_usedstaysfalse.