Table of Contents

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

verifier ICredentialVerifier
mdocVerifier MdocVerifier
encryptionKeys ResponseEncryptionKeyStore

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

verifier ICredentialVerifier
mdocVerifier MdocVerifier
encryptionKeys ResponseEncryptionKeyStore
clock TimeProvider

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

request DcApiPresentationRequest

Returns

bool

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

request PresentationRequest

Returns

bool

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

session VerificationSession
response WalletResponseData
ct CancellationToken

Returns

Task<VerificationResult>

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

request DcApiPresentationRequest

The 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.

origin string

The 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.

responseDataJson string

The JSON of the data member of the credential the page received.

responseDecryptionKey SecurityKey

The private key the request's encryption key pairs with, for a dc_api.jwt response; null for a request that asked for a cleartext one, which then cannot be answered encrypted.

ct CancellationToken

Cancellation.

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

responseDecryptionKey is null for a request that asked for an encrypted response, or a required argument is null.