How to build mDocs proximity verification capabilities into my iOS application
This guide offers step-by-step instructions for using the iOS mDocs verifier SDK to build the capability to verify an mDoc presented via a proximity presentation workflow as per ISO/IEC 18013-5.
If you are unfamiliar with this presentation workflow, the corresponding tutorial might be a better starting point as it offers more context and a high level overview of the user experience.
Prerequisites
- Access to the SDK’s GitHub distribution repository. Refer to the getting started guide for more information.
Access requires an SSH key associated with the GitHub user who has access to the distribution repo. Please contact us if you are having trouble with setting this up.
Overview
This guide comprises the following steps:
- Setup your project.
- Initialize the SDK.
- Manage certificates.
- Verify an mDoc.
Setup your project
- Install the SDK.
- Add Bluetooth permissions to your application.
Initialize the SDK
- Create a new variable:
var mobileCredentialVerifier: MobileCredentialVerifier
- Initialize the SDK by creating a new instance of the
MobileCredentialVerifier
class and calling itsinitialize
function:
mobileCredentialVerifier = MobileCredentialVerifier.shared
try mobileCredentialVerifier.initialize()
Manage certificates
- Create a new view for managing issuer certificates.
- Create a UI element that calls the addTrustedIssuerCertificates function and enables the user to add a new certificate:
viewModel.addCertificate(certificateString)
...
func addCertificate(_ certificate: String) {
Task {
do {
_ = try await mobileCredentialVerifier.addTrustedIssuerCertificates(certificates: [certificate])
self.getCertificates()
}
catch {
print(error.localizedDescription)
}
}
}
- Create a UI element that displays existing certificates by calling the
getTrustedIssuerCertificates
function:
viewModel.getCertificates()
...
func getCertificates() {
do {
let fetchedCertificates = try mobileCredentialVerifier.getTrustedIssuerCertificates()
// Updating the UI from the main thread
DispatchQueue.main.async {
self.certificates = fetchedCertificates
}
} catch {
print(error.localizedDescription)
}
}
- Create a UI element that enables the user to remove an existing certificate by calling the
deleteTrustedIssuerCertificate
function:
.swipeActions(edge: .trailing) {
Button(role:. destructive) {
viewModel.removeCertificate(certificate.id)
} label: {
Image(systemName: "trash")
}
...
func removeCertificate(_ certificateID: String) {
do {
try mobileCredentialVerifier.deleteTrustedIssuerCertificate(certificateId: certificateID)
// Refresh the certificates list after deletion
self.getCertificates()
} catch {
print(error.localizedDescription)
}
}
}
Verify an mDoc
- Create a new presentation request to define the information you wish to verify:
let mobileCredentialRequest = MobileCredentialRequest(
docType: "org.iso.18013.5.1.mDL",
namespaces: [
"org.iso.18013.5.1.mDL": [
"family_name": false,
"first_name": false,
"birth_date": false
]
]
)
Based on your implementation, this request can be created in different ways:
- You can hardcode it into the application.
- You can create a number of different requests and create a UI element to let the user choose between them.
- You can create a UI element that lets the user create a custom request on their own.
- Create a variable to store the response from the wallet application:
@Published var receivedDocuments: [MobileCredentialPresentation] = []
- Integrate a QR scanning capability into your app. Refer to our
tutorial for an example
using
CodeScanner
.
This capability should enable your app to scan a QR code presented by a wallet application and
extract the deviceEngagement
string from it to initiate the proximity presentation session.
- Call the
createProximityPresentationSession
function with theString
obtained from the QR code to:- Establish a secure connection with the wallet application device.
- Send a presentation request by calling the
requestMobileCredentials
function with an array ofMobileCredentialRequests
which includes the relevant presentation requests:
func setupProximityPresentationSession(_ string: String) {
Task {
do {
let _ = try await mobileCredentialVerifier.createProximityPresentationSession(
encodedDeviceEngagementString: string,
onSessionTerminated: { _ in print("Session Terminated") }
)
sendDeviceRequest()
} catch {
print(error.localizedDescription)
}
}
}
...
func sendDeviceRequest() {
Task { @MainActor in
do {
// Refresh the list of received documents
if !receivedDocuments.isEmpty {
receivedDocuments = []
}
// Find the existing proximity presentation session.
let presentationSession = try? mobileCredentialVerifier.getCurrentProximityPresentationSession()
// Request mDocs
let deviceResponse = try await presentationSession?.requestMobileCredentials(
request: [mobileCredentialRequest]
)
// Assign new values from the response
receivedDocuments = deviceResponse?.credentials ?? []
// Terminate session after response is received (optional)
await presentationSession?.terminateSession()
} catch {
print(error)
receivedDocuments = []
}
}
}
The
requestMobileCredentials
function returns an instance of
MobileCredentialResponse
which can be stored in a variable.
- Create a new view for using the MobileCredentialResponse instance to display verification results to the verifier app user.