light-mode-image
Learn
WebGuides

Handling verification results

Learn how to retrieve and interpret mDoc verification results in your web application

When a holder responds to a web verification request, that response includes structured data containing the verification outcome. This guide explains the different types of responses your web application can receive as a verifier and how to access them.

Result delivery methods

The way your web application receives verification results depends on your MATTR VII verifier application configuration:

Front channel delivery (resultAvailableInFrontChannel: true): Results are returned directly to your web application through the Verifier Web SDK as a RequestCredentialsResponse object.

Back channel delivery (resultAvailableInFrontChannel: false): Your backend retrieves results by calling the retrieve presentation session result endpoint, receiving them as a 200 response.

For more details on how these delivery methods work within the complete verification flow, see the workflow guide.

Production implementations should use back channel delivery with a backend. This provides better security through challenge validation, protecting against session replay attacks.

Regardless of the delivery method, the same information is available in both response structures. The key difference is where and how you retrieve it.

Understanding response types

When a holder responds to a verification request, you receive one of two high-level result types, depending on whether the presentation workflow was completed successfully or not.

Presentation failed

In this case, the holder was unable to complete the presentation workflow. This can happen for various reasons, such as the user canceling the request, the wallet being unavailable, or an error occurring during presentation processing.

You will receive a PresentationFailureResult object containing:

  • sessionId: The unique identifier for this verification session
  • challenge: The challenge used to verify response authenticity
  • credentialQuery: The original request defining what credentials and claims were requested
  • error: Object with type and message fields

The error.type indicates why the presentation failed:

  • WalletUnavailable: The wallet appears to be unavailable and unable to respond to the request
  • SessionAborted: User explicitly aborted the session before it timed out
  • ResponseError: Received an error presentation response
  • VerificationError: The submitted presentation response is invalid
  • Unknown: Encountered an unknown error while processing the presentation response

Example: User cancels the mDL presentation request:

Example presentation failure response for user cancellation
{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
  "credentialQuery": [
    {
      "profile": "mobile",
      "docType": "org.iso.18013.5.1.mDL",
      "nameSpaces": {
        "org.iso.18013.5.1": {
          "family_name": { "intentToRetain": false },
          "given_name": { "intentToRetain": false },
          "birth_date": { "intentToRetain": false }
        }
      }
    }
  ],
  "error": {
    "type": "SessionAborted",
    "message": "User aborted the session"
  }
}

Presentation succeeded

In this case, the holder successfully completed the presentation workflow. You will receive a PresentationSuccessResult object containing:

  • sessionId: The unique identifier for this verification session
  • challenge: The challenge used to verify response authenticity
  • credentialQuery: The original request defining what credentials and claims were requested
  • credentials (optional): Array of verified credentials with their claims and verification status
  • credentialErrors (optional): Array of errors for credentials that couldn't be returned

A successful presentation can include several scenarios, often in combination:

  1. No matching credentials: The holder doesn't have the requested credentials (the credentialErrors array will detail which credentials were not returned with an error code of notReturned)
  2. Verification failed: Credentials were provided but verification failed (the credentials array will contain credentials with verified: false)
  3. Verification succeeded for all requested claims: Credentials were verified successfully and all requested claims were returned (the credentials array will contain credentials with verified: true and no related claimErrors)
  4. Partial success with claim-level issues: One or more credentials were verified (verified: true), but some requested claims within those credentials were missing or failed. These issues are reported in the claimErrors field for each affected credential and can appear alongside any of the above scenarios.

Detailed result structure

When a presentation succeeds, the result includes detailed information at multiple levels:

Credential-level information

Each credential in the credentials array contains:

  • docType: The credential type (e.g., org.iso.18013.5.1.mDL for a mobile driver's license).
  • claims: Verified claims organized by namespace.
  • claimErrors: Errors for individual claims that couldn't be verified or were not returned.
  • validityInfo: Credential validity period timestamps.
  • verificationResult: Verification status containing:
    • verified: Boolean indicating if verification succeeded (this is a high-level result and individual claim errors may still exist).
    • reason (optional): Object with type and message explaining verification failures (if such failures exist). The following reason.type values are possible:
      • DeviceKeyInvalid: Device key is not valid. This can occur if the credential was not properly bound to the device or if the device's secure element is compromised.
      • InvalidSignerCertificate: Invalid signer certificate. This can occur if the credential's signing certificate is not valid or has been tampered with.
      • IssuerNotTrusted: Credential was issued by a certificate that is not trusted by the verifier. This can occur if the issuer's certificate is not included in the verifier's trusted issuer list.
      • MobileCredentialExpired: Credential expired. This can occur if the current date is after the credential's validUntil date.
      • MobileCredentialInvalid: Credential is not valid. This can occur for various reasons such as failing signature verification, containing invalid data, or not conforming to expected formats.
      • MobileCredentialNotYetValid: Credential not yet valid. This can occur if the current date is before the credential's validFrom date.
      • StatusRevoked: Credential has been revoked. This can occur if the issuer has revoked the credential after it was issued, which is typically checked through a revocation mechanism provided by the issuer.
      • StatusUnknown: Credential status could not be determined. This can occur if the verifier is unable to check the revocation status of the credential due to network issues or if the issuer does not provide a revocation mechanism.
      • TrustedIssuerCertificateExpired: Trusted issuer certificate expired. This can occur if the certificate of the trusted issuer has passed its expiration date, which may affect the trustworthiness of credentials issued by that issuer.
      • TrustedIssuerCertificateNotYetValid: Trusted issuer certificate not yet valid. This can occur if the certificate of the trusted issuer is not yet valid (i.e., the current date is before the certificate's validFrom date), which may affect the trustworthiness of credentials issued by that issuer.
      • UnsupportedCurve: Credential object contains unsupported curve. This can occur if the credential uses cryptographic curves that are not supported by the verifier's cryptographic library, which may prevent successful verification of the credential's signatures.
  • issuerInfo: Issuer details including commonName and trustedIssuerId.
  • branding (optional): Visual information for displaying the credential (name, description, colors, logos). You can use this information to create a rich user interface when showing the credential details in your application.

Claim-level information

Claims are organized by namespace within the claims object. For example, for an mDL, claims will appear under the org.iso.18013.5.1 namespace:

Example claims structure for a verified mDL credential
"claims": {
	"org.iso.18013.5.1": {
		"family_name": { "value": "Smith" },
		"given_name": { "value": "Jane" },
		"birth_date": { "value": "1990-05-15" },
		"address": { "value": "123 Main Street, Springfield" }
	}
}

If specific claims couldn't be verified or weren't provided, they appear in the claimErrors object with the same namespace structure and an error code of notReturned:

Example claim errors structure for a credential with a missing claim
"claimErrors": {
	"org.iso.18013.5.1": {
		"portrait": "notReturned"
	}
}

Credential errors

When a requested credential wasn't provided by the holder, it appears in the credentialErrors array with a docType and an errorCode of notReturned:

Example credential errors structure for a missing credential
"credentialErrors": [
	{
		"docType": "org.iso.18013.5.1.mDL",
		"errorCode": "notReturned"
	}
]

Complete examples

No matching credentials

The holder doesn't have the requested mDL:

Example response for no matching credentials
{
	"sessionId": "550e8400-e29b-41d4-a716-446655440000",
	"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
	"credentialQuery": [
		{
			"profile": "mobile",
			"docType": "org.iso.18013.5.1.mDL",
			"nameSpaces": {
				"org.iso.18013.5.1": {
					"family_name": { "intentToRetain": false },
					"given_name": { "intentToRetain": false }
				}
			}
		}
	],
	"credentialErrors": [
		{
			"docType": "org.iso.18013.5.1.mDL",
			"errorCode": "notReturned"
		}
	]
}

Verification failed

The holder presents an mDL but it has expired:

Example response for a verification failure due to expired mDL
{
	"sessionId": "550e8400-e29b-41d4-a716-446655440000",
	"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
	"credentialQuery": [
		{
			"profile": "mobile",
			"docType": "org.iso.18013.5.1.mDL",
			"nameSpaces": {
				"org.iso.18013.5.1": {
					"family_name": { "intentToRetain": false },
					"given_name": { "intentToRetain": false },
					"birth_date": { "intentToRetain": false }
				}
			}
		}
	],
	"credentials": [
		{
			"docType": "org.iso.18013.5.1.mDL",
			"verificationResult": {
				"verified": false,
				"reason": {
					"type": "MobileCredentialInvalid",
					"message": "Credential has expired"
				}
			},
			"validityInfo": {
				"signed": "2024-01-15T10:00:00Z",
				"validFrom": "2024-01-15T10:00:00Z",
				"validUntil": "2025-01-15T10:00:00Z",
				"expectedUpdate": "2026-01-15T10:00:00Z"
			}
		}
	]
}

Verification succeeded

The holder successfully presents a valid mDL:

{
	"sessionId": "550e8400-e29b-41d4-a716-446655440000",
	"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
	"credentialQuery": [
		{
			"profile": "mobile",
			"docType": "org.iso.18013.5.1.mDL",
			"nameSpaces": {
				"org.iso.18013.5.1": {
					"family_name": { "intentToRetain": false },
					"given_name": { "intentToRetain": false },
					"birth_date": { "intentToRetain": false },
					"address": { "intentToRetain": false }
				}
			}
		}
	],
	"credentials": [
		{
			"docType": "org.iso.18013.5.1.mDL",
			"claims": {
				"org.iso.18013.5.1": {
					"family_name": { "value": "Smith" },
					"given_name": { "value": "Jane" },
					"birth_date": { "value": "1990-05-15" },
					"address": { "value": "123 Main Street, Springfield" }
				}
			},
			"validityInfo": {
				"signed": "2024-01-15T10:00:00Z",
				"validFrom": "2024-01-15T10:00:00Z",
				"validUntil": "2027-01-15T10:00:00Z",
				"expectedUpdate": "2028-01-15T10:00:00Z"
			},
			"verificationResult": {
				"verified": true
			},
			"issuerInfo": {
				"commonName": "State Department of Motor Vehicles",
				"trustedIssuerId": "d4a6e9f2-3b1c-4d8e-a5f7-9c2b0e8d1a3f"
			},
			"branding": {
				"name": "Driver License",
				"description": "State-issued driver license",
				"backgroundColor": "#1E3A8A",
				"issuerLogo": {
					"format": "svg",
					"data": "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg=="
				}
			}
		}
	]
}

Front channel vs back channel details

Front channel delivery

When using resultAvailableInFrontChannel: true, the Verifier Web SDK's requestCredentials function returns a RequestCredentialsResponse:

type RequestCredentialsResponse = {
	sessionId: string;
	result?: PresentationSessionResult;
	sessionCompletedInRedirect?: boolean;
};

Where result contains either a PresentationSuccessResult or PresentationFailureResult as detailed above.

Back channel delivery

When your backend retrieves results from the MATTR VII tenant:

GET /v2/presentations/sessions/{sessionId}/result

The response is either a PresentationSuccessResult or PresentationFailureResult with the same structure as front channel results.

Backend implementation steps:

  1. Retrieve verification results using the session ID
  2. Validate the returned challenge matches the challenge generated before starting the session
  3. Process the results according to your business logic
  4. Return relevant information to your web application

Challenge validation in the backend protects against session replay attacks. Generate a unique challenge when creating the session, and verify it matches when retrieving results.

Next steps

How would you rate this page?

Last updated on

On this page