Requesting and verifying mDocs

Overview

The core SDK functionality is to request and verify mDocs via a proximity presentation workflow as per ISO/IEC 18013-5:2021.

To build a step-by-step implementation of this workflow, give the Proximity verification tutorial a try.

Sequence diagram

Detailed steps

Create a presentation request

As a verifier, you can select what information you request for verification by creating an instance of the SDK’s MobileCredentialRequest structure:

MobileCredentialRequest
var docType: MobileCredentialDataTypes.DocType
let namespaces: [MobileCredentialDataTypes.NameSpace : [MobileCredentialDataTypes.ElementID : MobileCredentialDataTypes.IntentToRetain]]
  • docType : Indicates the requested credential type.
  • namespaces : This is a dictionary of namespaces that are requested for verification. Each namespace is itself a dictionary of:
    • ElementID : Requested claim identifier.
    • IntentToRetain : Boolean indicating whether or not your application intends to retain this claim’s value after the verification process is completed. Setting this to true doesn’t actually store any information. It merely informs the holder that you intent to retain that information. Retaining the claim should be implemented separately.

This is the structure that will be shared with the holder’s wallet application as part of the verification workflow. It enables the wallet application to inform the holder what information is requested for verification.

UX Considerations and best practices

Your verifier application can either use hardcoded requests, or create a UI element that enables the user to create different requests on the fly by selecting different combinations of credential types, namespaces and claims. Check out our GO Verify app to see this is action.

Retrieve device engagement string from QR code presented by holder

As defined in ISO/IEC 18130-5:2021, a proximity presentation workflow is always initiated by the holder, who must create a QR code for the verifier to scan in order to initiate the device engagement phase.

This means that your application must be able to scan and process this QR code. You can see an example of implementing a third party framework to achieve this in the Proximity verification tutorial.

Once the QR code is scanned and processed, you should be able to retrieve the device engagement string embedded in it. This string must then be used to establish a secure connection between the holder and verifier devices.

Create a proximity presentation session

To establish a secure connection between the holder and verifier devices, your verifier application must call the SDK’s createProximityPresentationSession method:

createProximityPresentationSession
func createProximityPresentationSession(
    encodedDeviceEngagementString: String,
    onSessionTerminated sessionTerminatedAction: ((ProximityPresentationSessionTerminationError?) -> Void)? = nil
) async throws -> ProximityPresentationSession
  • encodedDeviceEngagementString : The string retrieved from the QR code presented by the holder.

Once called, the createProximityPresentationSession method will establish a secure connection with the holder application and return an instance of the ProximityPresentationSession class.

Send a presentation request

Once the connection is established, your verifier application should call the ProximityPresentationSession class’ requestMobileCredentials method to request information for verification:

requestMobileCredentials
func requestMobileCredentials(
    request: [MobileCredentialRequest],
    skipStatusCheck: Bool = false
) async throws -> MobileCredentialResponse
  • request : This is the instance of the SDK’s MobileCredentialRequest structure referenced above.
  • skipStatusCheck : Controls whether credential revocation status is checked (false) or not (true).

As per ISO/IEC 18013, once a valid request is sent a response is expected:

  • When a response is received from the holder it is decoded, verified and returned by the method as an instance of the MobileCredentialResponse class.
  • If no response is received after 300 seconds the request will timeout and a TimeoutError error thrown. The session will not be terminated and your verifier application can send a new request if required.

UX Considerations and best practices

As per ISO/IEC 18013, a credential presentation and a sessionTermination status code can be sent by the holder in a single response. In this scenario the method will return the credential presentation and then immediately execute the onSessionTerminate(_:) callback, closing the data transport session.

Handle the presentation response

The holder’s response is returned by the requestMobileCredentials method as an instance of the MobileCredentialResponse structure:

MobileCredentialResponse
let credentialErrors: [CredentialError]?
let credentials: [MobileCredentialPresentation]?
  • credentials : This is an array of credentials included in the holder’s response, represented as MobileCredentialPresentation structure(s):
MobileCredentialPresentation
let branding: Branding?
let claimErrors: [MobileCredentialDataTypes.NameSpace : [MobileCredentialDataTypes.ElementID : MobileCredentialResponseErrorCode]]?
let claims: [MobileCredentialDataTypes.NameSpace : [MobileCredentialDataTypes.ElementID : MobileCredentialElementValue]]?
let docType: MobileCredentialDataTypes.DocType
let issuerInfo: IssuerInfo?
let validityInfo: Validity
let verificationResult: VerificationResult
  • branding : Information and links to graphic assets that should be used by your wallet application to render this credential.
  • claims : This is a dictionary of any errors found with specific claims included in the credential.
  • claims : This is a dictionary of namespaces that are included in the credential, the identifiers (ElementID) of claims that were requested for verification and their values (MobileCredentialElementValue).
  • doctype : Credential’s type.
  • issuerInfo :
    • commonName : Issuer’s common name, matching its certificate. This can be used to display the credential issuer’s human readable name.
    • trustedIssuerCertificateId : Issuer’s IACA certificate.
  • validityInfo :
    • validFrom : Indicates the date when this credential becomes valid.
    • validUntil : Indicates the date when this credential expires.
  • VerificationResult:
    • reason : Verification failure reason (when applicable):
      • message : Verification failure message.
      • type : Verification failure type.
    • verified : Boolean indicating whether verification was successful (true) or not (false).

Your verifier application can now parse this instance and display relevant information to the user.

Verification failures

If validation fails, one of the following errors can be returned in verificationResult.reason.type:

TypeDescription
DeviceKeyInvalidWhen an issuer issues an mDoc to a holder, they can optionally limit what claims from the mDoc the holder can present. If a holder attempts to present claims that they are not allowed to present (as per the issuer’s policy), this error is returned.
InvalidSignerCertificateIndicates an error in the certificate used to sign the credential. No information included in the credential can be trusted.
MobileCredentialExpiredCredential has expired.
MobileCredentialInvalidCaptures different scenarios where the credential cannot be validated due to tampering, decoding problems and others. No information included in the credential can be trusted.
MobileCredentialNotYetValidCredential has future activation date.
StatusRevokedCredential has been permanently revoked.
StatusSuspendedCredential has been temporarily revoked.
StatusUnknownUnable to retrieve the status list referenced in the credential and determine its revocation status.
TrustedIssuerCertificateExpiredIssuer IACA certificate expired.
TrustedIssuerCertificateNotYetValidCredential was signed with a certificate that has a future activation date (e.g. valid from future date).
UnsupportedCurveThe SDK currently only supports NIST P-*-based curves from the ISO/IEC 18013-5:2021 standard. If the credential was signed using any other curve, this error is returned and the credential cannot be verified.