Proximity (in-person) presentation
The SDK enables presenting a claimed mDoc for verification via a proximity presentation workflow as per ISO 18013-5.
To build a step-by-step implementation of this workflow, give the Proximity presentation tutorial a try.
Sequence diagram
Detailed steps
Display a QR code with an embedded device engagement String
The ISO/IEC 18130-5:2021 standard defines that a proximity presentation workflow is always initiated by the holder (wallet user), who must create a QR code for the verifier to scan in order to initiate the device engagement phase.
Thus, your wallet application must provide a UI element for the user to interact with in order to
trigger device engagement with the verification device by calling the SDK’s
createProximityPresentationSession
method:
func createProximityPresentationSession(
onRequestReceived requestReceivedAction: @escaping ([(request: MobileCredentialRequest, matchedMobileCredentials: [MobileCredentialMetadata])]?, ProximityPresentationSessionError?) -> Void,
onConnected onConnectedAction: (() -> Void)? = nil,
onSessionTerminated sessionTerminatedAction: ((ProximityPresentationSessionTerminationError?) -> Void)? = nil,
mobileCredentialAuthenticationOption: MobileCredentialAuthenticationOption = .signature,
bleMode: BLEMode = .mDocClientCentral
) async throws -> ProximityPresentationSession
mobileCredentialAuthenticationOption
: Device authentication options for credentials presented in the current session:signature
(default): Authenticates the credential based on its digital signature.mac
: Authenticates the credential by computing the device Message Authentication Code (MAC).
bleMode
: BLE mode to use for data transfer:mDocClientCentral
(default): The holder acts as a client and the verifier acts as a server.mDocPeripheralServer
: The holder acts as a server and the verifier acts as a client.
This method returns a
ProximityPresentationSession
instance, which includes a deviceEngagement
string in Base64
format. This string contains the
information required to establish a secure connection, including:
- Wireless communication protocols supported by the holder.
- How the verifier can connect with the holder.
- Ephemeral public key which is unique to the current session.
- Additional feature negotiations.
Your wallet application will need to convert this string into a QR code and display it for the verifier device to scan. You can see an example implementation in the Proximity presentation tutorial.
UX Considerations and best practices
This method requires granting bluetooth permissions to your wallet application. To enable this, you
must add the NSBluetoothAlwaysUsageDescription
attribute to the application’s info.plist
file.
When calling this method for the first time, a system UI will prompt the user to grant bluetooth
permissions to the application. If the user has denied access, the
MobileCredentialHolderError.bluetoothPermissionDenied
error is thrown and the workflow cannot
continue until bluetooth permissions are granted to the application. Your wallet application should
provide a UX to cover this scenario.
Handle the verification request
After the SDK’s
createProximityPresentationSession
method is called it enters a listening state and can handle three types of events:
onConnected
: When a secure connection is established with the verifier application. This can be used by your wallet application to provide a successful connection indication to the user.onSessionTerminated
: When a secure connection is terminated for whatever reason. This can be used by your wallet application to indicate a terminated connection and advice how to proceed.onRequestReceived
: When a presentation request is received from the verifier. This event should be used by your wallet application to display the verification request to the user.
When the SDK receives a verification request from the connected verifier (onRequestReceived
event), the
createProximityPresentationSession
method returns an array that includes pairs of requested and matching credentials:
[(request: MobileCredentialRequest, matchedMobileCredentials: [MobileCredentialMetadata])]
Your wallet application can now parse these structures and display to the user:
- What information is requested for verification.
- What existing credentials match the requested information.
- What claims from these existing credentials will be shared with the verifier.
Then, your wallet application should include a UI element for the user to consent sharing the information with the verifier:

UX Considerations and best practices
The MATTR GO example app splits this information into two screens:
- The first screen displays what information is requested for verification.
- Once the users choose to continue, a second screen is displayed with the matching credentials and a consent button.
You can choose to follow a similar approach or combine all information into a single view, depending on your UX/UI preferences.
Whatever approach you choose, consider creating a single view that is used for both the proximity and online presentation flows for a more consistent UX.
request
and matchedMobileCredentials
structure
The array returned by the
createProximityPresentationSession
method when a verification request is received from the verifier (onRequestReceived
event)
includes the following structures:
-
request
: This is aMobileCredentialRequest
structure that defines the information requested for verification:MobileCredentialRequest structurevar 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 the relying party will retain this claim’s value after the verification process is completed.
-
matchedMobileCredentials
: This is aMobileCredentialMetadata
structure that includes the metadata of stored credentials that include the information included in the correspondingMobileCredentialRequest
:matchedMobileCredentials structurelet branding: Branding? let claims: [MobileCredentialDataTypes.NameSpace : [MobileCredentialDataTypes.ElementID]]? let docType: String let id: String let issuerInfo: IssuerInfo let validityInfo: Validity
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 namespaces that are included in the credential and the identifiers (ElementID
) of claims that are requested for verification from this credential.doctype
: Credential’s type.id
: Unique identifier of this credential.issuerInfo
:commonName
: Issuer’s common name, matching its certificate. This can be used to display the credential issuer’s human readable name to the user.trustedIssuerCertificateId
: Issuer’s IACA certificate.
validityInfo
:validFrom
: Indicates the date when this credential becomes valid.validUntil
: Indicates the date when this credential expires.
The
MobileCredentialMetadata
structure does not include any of the credential claims or verification status. If you want to display this information to the user as part of the verification workflow, use the getCredential method with the credential’sid
to retrieve this information as an instance of MobileCredential. You can than parse this structure and display any required information to the user.
Send presentation response
When the user consents to sharing the displayed information with the verifier, your wallet
application must call the SDK’s
sendResponse
method to share the selected credentials with the verifier:
func sendResponse(credentialIds: [String], terminateSession: Bool = false) async throws
credentialIds
: Use this array to include the identifiers of all credentials that should be included in the response to the verifier.autoRedirect
: Controls the application behavior after a response is sent:- When set to
true
, the session is terminated as soon as a response is sent. - When set to
false
, your application can manually terminate the session when appropriate.
- When set to
UX Considerations and best practices
- For large credentials, it is recommended to set
autoRedirect
tofalse
to ensure the entire credential was received by the verifier before terminating the session. - Some verification requests might include more than one credential. Furthermore, the user might have more than one credential that matches the verification request. Your wallet application should therefore offer a UI to enable the user to select what credential(s) to share in the response.
Continue the interaction with the verifier
Once the response is sent by your wallet application, it can be verified by the verifier application, and the in-person interaction can continue based on the verification results.