Wallet validates the wallet_nonce in the returned request object
OID4VP 1.0 §5.10.1MUSTRoles: wallet
Requirement as recorded in the ProtocolSoup registry
Additionally, if the Wallet passed a wallet_nonce in the POST request, the Wallet MUST validate whether the request object contains the respective nonce value in a wallet_nonce claim. If it does not, the Wallet MUST terminate request processing.
Read §5.10.1 in OID4VP 1.0Self-test verdict
PassCommit 011029cEvaluated
This is ProtocolSoup's result against its own implementation at the commit shown. It is not a certification of ProtocolSoup or of any other product.
Tests
- TestFetchRequestObjectPOSTChecksWalletNonce
./cmd/walletharness
Pass
Implementation
Explainer
What this requires
With request_uri_method=post, the Wallet may send a wallet_nonce when it fetches the request object. Section 5.10 defines it as "A string value used to mitigate replay attacks of the Authorization Request" and tells the Verifier that "When received, the Verifier MUST use it as the wallet_nonce value in the signed authorization request object." Section 5.10.1 puts the check on the Wallet: if the returned request object does not carry the same value in a wallet_nonce claim, the Wallet stops processing the request.
Sending the nonce is optional. Checking it, once sent, is not.
Why it exists
The nonce only helps if someone checks it. A request object signed over a nonce the Wallet chose a moment earlier cannot be a copy captured from another exchange and replayed. The Wallet is the only party that knows which nonce it sent, so it is the only one that can make that check. A Wallet that sends a nonce and ignores the answer gets no replay protection at all.
What non-compliance looks like
The Wallet sends wallet_nonce, discards it, and processes whatever request object comes back: one with no wallet_nonce claim, one with a different value, or one served unchanged from an earlier session. The Verifier's binding (VP-008) then protects nothing, because a replayed object passes the Wallet just as a fresh one does.
How ProtocolSoup tests it
The hosted wallet's fetchRequestObject keeps the random wallet_nonce it POSTs and, once the response is a compact JWS, calls requireRequestObjectWalletNonce. A missing claim, a different value or a non-string claim ends processing with an error that cites Section 5.10.1. The request object's signature is verified afterwards, so a matching claim in an object the Verifier did not sign still fails. GET retrieval sends no nonce and is unaffected.
TestFetchRequestObjectPOSTChecksWalletNonce runs a test Verifier that receives the POSTed wallet_nonce and builds the request object from it. It asserts that an echoed nonce is accepted and returned unchanged. It also asserts that the Wallet terminates with a wallet_nonce error when the claim is missing, carries a different value, or is not a string.