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:
val presentationSession: ProximityPresentationSession =
MobileCredentialHolder.getInstance().createProximityPresentationSession(
activity = activity, // Used for user authentication, not kept after
authenticationOption = AuthenticationOption.Signature, // See below
bleMode = BleMode.MDocClientCentral, // See below
onRequestReceived = { session: ProximityPresentationSession, matchedCredentials: List<CredentialRequestInfo>?, error: Throwable? ->
// Handle the received request. You probably want to show the requested credentials to
// the user, get their consent, and send the credentials to the Verifier after the
// consent is received.
},
onConnected = {
// You can indicate the established session on the UI if you want
},
onSessionTerminated = { error: HolderException? ->
// Handle a session termination
}
)
authenticationOption
: 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
This method requires granting bluetooth permissions to your application.
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
HolderException.BluetoothPermissionException
exception 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 a
CredentialRequestInfo
instance which includes a
matchedCredentials
property. This property details any existing credentials that match the request using an instance of
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 Consideration
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:
-
MobileCredentialRequest
represents the information requested for verification:MobileCredentialRequest structuredata class MobileCredentialRequest( val docType: DocType, // String val nameSpaces: NameSpaces )
-
docType
: Indicates the requested credential type. -
namespaces
: This is a map of namespaces that are requested for verification. Below is a description of thenamespaces
data structure:[ NameSpace1 { // String. Requested namespace. DataElements1 { DataElementIdentifier // String. Requested claim identifier. IntentToRetain // Boolean indicating whether or not the relying party // will retain this claim’s value after the // verification process is completed. } }, NameSpace2 { ... } ]
-
-
matchedMobileCredentials
: This is aMobileCredentialMetadata
structure that includes the metadata of stored credentials that include the information included in the correspondingMobileCredentialRequest
:matchedMobileCredentials structuredata class MobileCredentialMetaData( val id: String, val issuerInfo: IssuerInfo, val docType: String, val validityInfo: MobileCredentialValidity, val claims: Map<String, Set<String>>, val branding: Branding? = null )
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.
doctype
: Credential’s type.validityInfo
:validFrom
: Indicates the date when this credential becomes valid.validUntil
: Indicates the date when this credential expires.
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.branding
: Information and links to graphic assets that should be used by your wallet application to render this credential.
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:
val presentationSession: ProximityPresentationSession = ... // Object that we received above
val credentialIds: List<String> = ... // Credential IDs, selected by the user
presentationSession.sendResponse(
credentialIds = credentialIds,
activity = activity, // Required for user authentication, not kept after
terminateSession = true
)
credentialIds
: Use this array to include the identifiers of all credentials that should be included in the response to the verifier.terminateSession
: 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
- The SDK’s
sendResponse
method requires user authentication if the user has not authenticated in the last 30 seconds. - 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.