Class WalletResponseVerifier
- Namespace
- Tessio.Verifier.AspNetCore
- Assembly
- Tessio.Verifier.AspNetCore.dll
Default IWalletResponseVerifier. Parses a wallet response format-aware (from the session's
request), then verifies each credential with expectations derived from that same request — audience from
client_id, nonce, and the requested vct / docType — rather than from the process-wide
VerifierOptions. Verifying against the session's own client_id is what makes the seam
multi-tenant correct, and it also closes the app-wide-audience gap for the built-in callback endpoint,
which routes through VerifyParsedAsync(VerificationSession, ParsedWalletResponse, CancellationToken). A response returned through the Digital Credentials
API is verified by VerifyDcApiAsync(DcApiPresentationRequest, string, string, SecurityKey?, CancellationToken), with the same checks bound to the page's origin instead
of a client_id.
public sealed class WalletResponseVerifier : IWalletResponseVerifier
- Inheritance
-
WalletResponseVerifier
- Implements
- Inherited Members
Constructors
WalletResponseVerifier(ICredentialVerifier, MdocVerifier, ResponseEncryptionKeyStore)
Creates a verifier over the SD-JWT VC and mdoc credential verifiers, on the system clock.
public WalletResponseVerifier(ICredentialVerifier verifier, MdocVerifier mdocVerifier, ResponseEncryptionKeyStore encryptionKeys)
Parameters
verifierICredentialVerifiermdocVerifierMdocVerifierencryptionKeysResponseEncryptionKeyStore
WalletResponseVerifier(ICredentialVerifier, MdocVerifier, ResponseEncryptionKeyStore, TimeProvider)
Creates a verifier over the SD-JWT VC and mdoc credential verifiers. clock decides when a
Digital Credentials API request has expired.
public WalletResponseVerifier(ICredentialVerifier verifier, MdocVerifier mdocVerifier, ResponseEncryptionKeyStore encryptionKeys, TimeProvider clock)
Parameters
verifierICredentialVerifiermdocVerifierMdocVerifierencryptionKeysResponseEncryptionKeyStoreclockTimeProvider
Methods
CanVerify(DcApiPresentationRequest)
Whether a stored Digital Credentials API request still carries the DCQL query a response is checked against, by the same test as CanVerify(PresentationRequest). Call it first and refuse a request that fails it, for the reasons that method gives.
public static bool CanVerify(DcApiPresentationRequest request)
Parameters
requestDcApiPresentationRequest
Returns
CanVerify(PresentationRequest)
Whether a stored request still carries the DCQL query verification checks a response against. It
is a check on the request being present and readable, not on every parameter in it: a request that
passes here can still be missing a response_uri, and an mdoc response would then fail
device authentication.
public static bool CanVerify(PresentationRequest request)
Parameters
requestPresentationRequest
Returns
Remarks
For a host that persists sessions itself. A request delivers its parameters either as claims in its signed request object or as plain query parameters, and rows written before a host persisted either one have neither. Call this first and refuse such a session.
Verifying one instead does not fail cleanly, it fails in two different wrong ways. The audience
and nonce still hold, because those come from the session rather than from the request, but the
credential type goes unchecked: no expected type skips the type comparison
(SdJwtVcVerifier) and a null ExpectedDocType skips the document-type comparison
(MdocVerifier), so a credential of the wrong type passes. Meanwhile an mdoc response fails
device authentication, because the transcript it signs covers a response_uri this session can no
longer produce. Neither outcome tells the caller what actually went wrong.
VerifyAsync(VerificationSession, WalletResponseData, CancellationToken)
Parses response (picking SD-JWT vs mdoc from the session's request, so mixed-format
tenants share one process) and verifies every presented credential against session.
A malformed or undecryptable response yields an invalid result (error code response_invalid)
rather than throwing, so the caller can always complete the session with the outcome. An Authorization
Error Response yields WalletError: in the clear from 0.25.0, sealed in a
direct_post.jwt response from 0.26.0. Before that it yielded response_invalid.
public Task<VerificationResult> VerifyAsync(VerificationSession session, WalletResponseData response, CancellationToken ct = default)
Parameters
sessionVerificationSessionresponseWalletResponseDatactCancellationToken
Returns
VerifyDcApiAsync(DcApiPresentationRequest, string, string, SecurityKey?, CancellationToken)
Verifies an OpenID4VP response returned through the Digital Credentials API against the request it answers.
public Task<VerificationResult> VerifyDcApiAsync(DcApiPresentationRequest request, string origin, string responseDataJson, SecurityKey? responseDecryptionKey, CancellationToken ct = default)
Parameters
requestDcApiPresentationRequestThe request as it was built and sent, stored whole in the host's own store. It is trusted as given: its origins, expiry and nonce become the expectations. A signed request's JWS is read without checking its signature again. Never take it from the page.
originstringThe origin of the page that called the API, as the browser serializes it (
window.location.origin, no trailing slash). It must be one the request names; the wallet bound its answer to the origin the browser gave it, so a page origin reported wrongly fails verification rather than passing it.responseDataJsonstringThe JSON of the
datamember of the credential the page received.responseDecryptionKeySecurityKeyThe private key the request's encryption key pairs with, for a
dc_api.jwtresponse; null for a request that asked for a cleartext one, which then cannot be answered encrypted.ctCancellationTokenCancellation.
Returns
- Task<VerificationResult>
The result. A malformed response is
response_invalid, not an exception.
Remarks
The request is refused before anything is parsed when it can no longer be verified
(request_unverifiable), when it has expired (request_expired) or when origin
is not one of its ExpectedOrigins (audience_mismatch).
Verifying does not use the request up. The host accepts one answer per request, as the redirect flow's session store does: a response that verified once verifies again, so a host that does not mark the request answered accepts a replayed one.
Exceptions
- ArgumentNullException
responseDecryptionKeyis null for a request that asked for an encrypted response, or a required argument is null.