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:
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. Eachnamespace
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 totrue
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:
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:
func requestMobileCredentials(
request: [MobileCredentialRequest],
skipStatusCheck: Bool = false
) async throws -> MobileCredentialResponse
request
: This is the instance of the SDK’sMobileCredentialRequest
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:
let credentialErrors: [CredentialError]?
let credentials: [MobileCredentialPresentation]?
credentials
: This is an array of credentials included in the holder’s response, represented asMobileCredentialPresentation
structure(s):
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
:
Type | Description |
---|---|
DeviceKeyInvalid | When 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. |
InvalidSignerCertificate | Indicates an error in the certificate used to sign the credential. No information included in the credential can be trusted. |
MobileCredentialExpired | Credential has expired. |
MobileCredentialInvalid | Captures different scenarios where the credential cannot be validated due to tampering, decoding problems and others. No information included in the credential can be trusted. |
MobileCredentialNotYetValid | Credential has future activation date. |
StatusRevoked | Credential has been permanently revoked. |
StatusSuspended | Credential has been temporarily revoked. |
StatusUnknown | Unable to retrieve the status list referenced in the credential and determine its revocation status. |
TrustedIssuerCertificateExpired | Issuer IACA certificate expired. |
TrustedIssuerCertificateNotYetValid | Credential was signed with a certificate that has a future activation date (e.g. valid from future date). |
UnsupportedCurve | The 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. |