light-mode-image
Learn
Guides

Handling verification results

Learn how to interpret mDoc verification results returned by the mDocs Verifier SDK in proximity presentation flows.

When a holder responds to an in-person (proximity) verification request, the mDocs Verifier SDK returns structured data containing the verification outcome. This guide explains the response structure and how to interpret it.

How results are delivered

In a proximity presentation flow, the holder's device communicates directly with your verifier application. After the holder responds to the presentation request, the SDK returns a MobileCredentialResponse object.

Your application receives the result inline and is responsible for parsing and acting on it according to your business logic.

Understanding the response

A MobileCredentialResponse contains two optional fields:

  • credentials: An array of MobileCredentialPresentation objects representing credentials that were successfully returned by the holder.
  • credentialErrors: An array of CredentialError objects representing credentials that couldn't be returned.

When a holder responds to a verification request, several outcomes are possible, 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 in their verificationResult.
  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 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 of each affected credential and can appear alongside any of the above scenarios.

Detailed result structure

Credential-level information

Each MobileCredentialPresentation 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 (signed, validFrom, validUntil, expectedUpdate).
  • verificationResult: Verification status containing:
    • verified: Boolean indicating if verification succeeded. This is a high-level result; individual claim errors may still exist.
    • reason (optional): Object explaining verification failures when verified is false. Contains a type value from the following:
      • 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 an 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 (optional): Issuer details including commonName and trustedIssuerId.
  • branding (optional): Visual information for displaying the credential (name, description, colors, logos). You can use this to create a rich user interface when showing credential details in your application.

Claim-level information

Claims are organized by namespace within the claims object. For example, for an mDL, claims 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 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 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 when the holder has no matching credentials
{
	"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 credential
{
	"credentials": [
		{
			"docType": "org.iso.18013.5.1.mDL",
			"verificationResult": {
				"verified": false,
				"reason": {
					"type": "MobileCredentialExpired",
					"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 with all requested claims:

Example response for a successful verification
{
	"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=="
				}
			}
		}
	]
}

Partial success with claim errors

The holder presents a valid mDL, but one of the requested claims was not returned:

Example response for a partial success with missing claims
{
	"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" }
				}
			},
			"claimErrors": {
				"org.iso.18013.5.1": {
					"portrait": "notReturned"
				}
			},
			"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"
			}
		}
	]
}

When processing a MobileCredentialResponse, follow these steps:

  1. Check for credential errors: Inspect credentialErrors to determine if any requested credentials were not returned by the holder. Handle these based on whether the credential is required for your use case.
  2. Iterate through credentials: For each MobileCredentialPresentation in the credentials array:
    • Check verificationResult.verified. If false, inspect verificationResult.reason to understand why.
    • If verified is true, proceed to extract claim values from the claims object.
    • Check claimErrors for any claims that were requested but not returned. Decide whether to proceed based on which claims are missing.
  3. Apply business logic: Use the verified claims, issuer information, and branding data to make authorization decisions and present results in your application.

Next steps

How would you rate this page?

Last updated on

On this page