Handling verification results
Learn how to interpret mDoc verification results returned by the mDocs Verifier SDK in remote mobile presentation flows.
When a holder responds to a remote mobile 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 remote mobile presentation flow, the holder's wallet app responds to a verification request initiated by your verifier app on the same device. After the holder consents to sharing their credentials, the SDK returns an OnlinePresentationSessionResult object.
Your application receives the result inline from the SDK and is responsible for parsing and acting on it.
Understanding the response
An OnlinePresentationSessionResult contains:
challenge(optional): The unique challenge of the session, used to verify response authenticity.mobileCredentialResponse(optional): AMobileCredentialResponsecontaining the credential data returned by the holder.error(optional): An error object if the presentation workflow could not be completed.
When the holder responds to a verification request, the result will either contain a mobileCredentialResponse or an error.
Session-level errors
If the error field is present, the holder was unable to complete the presentation workflow. The error object contains:
type: Indicates why the presentation failedmessage: A human-readable description of the error
The type values are:
SessionAborted: The user explicitly aborted the session before it completed.ResponseError: An error occurred while processing the response from the holder's wallet.VerificationError: The submitted presentation response is invalid.WalletUnavailable: The wallet appears to be unavailable and unable to respond to the request.Unknown: An unknown error occurred while processing the presentation response.
Example: The user cancels the mDL presentation request:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"error": {
"type": "SessionAborted",
"message": "User aborted the session"
}
}Credential response
When no session-level error occurs, the mobileCredentialResponse field contains the holder's response. A MobileCredentialResponse has two optional fields:
credentials: An array ofMobileCredentialPresentationobjects representing credentials that were successfully returned.credentialErrors: An array ofCredentialErrorobjects representing credentials that couldn't be returned.
A successful session (no error) can still result in several credential-level outcomes, often in combination:
- No matching credentials: The holder doesn't have the requested credentials. The
credentialErrorsarray will detail which credentials were not returned, with an error code ofnotReturned. - Verification failed: Credentials were provided but verification failed. The
credentialsarray will contain credentials withverified: falsein theirverificationResult. - Verification succeeded for all requested claims: Credentials were verified successfully and all requested claims were returned. The
credentialsarray will contain credentials withverified: trueand noclaimErrors. - 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 theclaimErrorsfield of each affected credential.
Detailed result structure
Credential-level information
Each MobileCredentialPresentation in the credentials array contains:
docType: The credential type (e.g.,org.iso.18013.5.1.mDLfor 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 whenverifiedisfalse. Contains atypevalue 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'svalidUntildate.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'svalidFromdate.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'svalidFromdate), 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 includingcommonNameandtrustedIssuerId.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:
"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:
"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:
"credentialErrors": [
{
"docType": "org.iso.18013.5.1.mDL",
"errorCode": "notReturned"
}
]Complete examples
Session error
The wallet couldn't be reached:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"error": {
"type": "WalletUnavailable",
"message": "The wallet is unavailable"
}
}No matching credentials
The holder doesn't have the requested mDL:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"mobileCredentialResponse": {
"credentialErrors": [
{
"docType": "org.iso.18013.5.1.mDL",
"errorCode": "notReturned"
}
]
}
}Verification failed
The holder presents an mDL but it has expired:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"mobileCredentialResponse": {
"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:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"mobileCredentialResponse": {
"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:
{
"challenge": "c5a27e4c-85b6-4b3c-9f1a-2d8e5f3a4b7c",
"mobileCredentialResponse": {
"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"
}
}
]
}
}Recommended handling flow
When processing an OnlinePresentationSessionResult, follow these steps:
- Check for session-level errors: If the
errorfield is present, the presentation workflow failed before any credential data was returned. Handle based on theerror.typevalue. - Validate the challenge: Compare the returned
challengeagainst the one you generated when creating the session. This protects against session replay attacks. - Check for credential errors: Inspect
mobileCredentialResponse.credentialErrorsto determine if any requested credentials were not returned. Handle these based on whether the credential is required for your use case. - Iterate through credentials: For each
MobileCredentialPresentationinmobileCredentialResponse.credentials:- Check
verificationResult.verified. Iffalse, inspectverificationResult.reasonto understand why. - If
verifiedistrue, proceed to extract claim values from theclaimsobject. - Check
claimErrorsfor any claims that were requested but not returned. Decide whether to proceed based on which claims are missing.
- Check
- Apply business logic: Use the verified claims, issuer information, and branding data to make authorization decisions and present results in your application.
Challenge validation protects against session replay attacks. Generate a unique challenge when creating the session, and verify it matches the one returned in the result.
Next steps
- Review the mDocs Verifier SDK API reference for iOS or Android for complete type definitions
- Explore the remote mobile verification workflow for the complete end-to-end process
- Follow the quickstart or tutorial for practical implementation examples
How would you rate this page?
Last updated on