Device-to-device configuration
Read more about D2D to understand the functionality. This article handles SDK-related configuration.
Setup
In a device-to-device setup, there are two web applications using the browser SDK. One web app starts a verification flow, and generates a QR code which links to the other web app. The second web app continues this verification flow. The primary device (the one starting the flow) is usually a computer or something with a comparatively poorer camera. The secondary device (the one continuing the flow) is usually a smartphone or something with a better camera. Both apps use the same web SDK, but have different configurations.
Configuration
The web SDK exposes an IdvFlowProps interface which is used to configure different devices:
export interface IdvFlowProps {
// ...
mode?: WorkingMode;
apiConfig: ProxyConfig | TransactionConfig;
enableD2D?: boolean;
// ...
}
Set the following flags:
- On the web app run by the primary device, set
enableD2Dtotrue. - On the web app run by the primary device, set
modeto"classic". TheapiConfigobject now expectsProxyConfigdata. - On the web app run by the secondary device, set
modeto"d2d". TheapiConfigobject now expectsTransactionConfigdata.
For example:
{
enableD2D: true,
mode: "classic",
apiConfig: {
url: 'address of your proxy',
workflowId: 'ID of your workflow',
d2d: { runAddress: 'address of the secondary app' },
},
consentData: {
userId: 'unique-user-id',
note: "lorem ipsum",
givenOn: new Date().toISOString(),
isTrainingAllowed: true,
isProcessingStoringAllowed: true,
}
}
And:
{
mode: "d2d",
apiConfig: {
apiUrl: 'Edge API URL from QR code',
transactionId: 'transaction ID from QR code',
ephemeralKey: 'ephemeral ID from QR code',
d2d: { joinKey: 'join key from QR code' },
},
}
These two minimal configurations are enough to initialize the primary and secondary web apps.
You can start verification flows using the createIdvFlow() function:
import { createIdvFlow } from "@microblink/platform-sdk/vanilla";
createIdvFlow({
// config object here
});
Or if you're using the React integration:
import { IdvFlow } from '@microblink/platform-sdk/react';
<IdvFlow
// config data here
/>
(In this case you must follow JSX syntax; we'll use plain JavaScript for the remainder of this article.)
D2D web app
You can either self-host or use the default Microblink web app for the secondary device. We explain the tradeoffs in the Run address article.
For the remainder of this article, we will assume that you are also hosting the secondary web app yourself.
Sequence
On the primary device (initiator), the SDK will:
- Initialize the D2D flow, including sending user consent.
- Generate a unique session identifier and QR code.
- Display the QR code to the user.
- Move to the
d2dIdlestate once connected. - Periodically poll session state from the Edge API to notify the user of possible changes (device connected, disconnected, etc.).
- Complete the flow (end in
d2dFlowEndstate) when verification is finished on the secondary device.
The secondary device executes the standard verification workflow but with the transaction details established by the primary device.
QR code
Generation (primary device)
The primary device generates a QR code containing the following fields:
{
"source": "DeviceToDevice",
"apiAddress": "https://api.us-east.platform.microblink.com/edge",
"transactionId": "0269368e51db07f3db5c0345a9",
"ephemeralKey": "ZG7.VR5M-[...]8=7T",
"redirectUrl": null,
"verificationLinkId": null,
"deviceJoinKey": "FR93=[...]b5V02o6YCA_lnKsp",
"deviceJoinKeyExpiresOn": "2025-12-08T08:43:01.8793126Z"
}
This information is encoded in a base64-encoded string and has a 5-minute validity period. When the QR code is generated, it points to your Run address, and appends this base64-encoded string as a query parameter. For example:
https://platform.microblink.com/run?sdk=eyJzb3VyY2UiOiJEZXZpY2VUb0RldmljZSIsImFwaUF...
Handling (secondary device)
The secondary device (web app) must receive the QR code information from the URL, and pass it into its configuration object. This means that you need to create logic that parses the URL and its query parameters.
If you've properly configured the secondary web app (see Configuration), you should be able to pass the URL parameters into your identity verification function directly, and continue with the flow started on the primary device.
For example, one way to parse the URL parameters would be:
const urlSearchParams = new URLSearchParams(window.location.search);
const data = urlSearchParams.get("sdk");
const jsonString = atob(data);
const result = JSON.parse(jsonString);
In this example we assume that all the parameters are base64-encoded data (a JSON object) passed to an sdk query parameter (https://example.com?sdk=...).
Examples
We provide a full example implementation here.
Here are some minimal examples that work, even though they should be expanded in production. For example, some things should be wrapped in try/except blocks, and you should generally have checks for presence on certain fields, rather than assume that they are there. We'll keep the examples here minimal for readability, and to focus on the D2D mechanism itself.
These examples also assume that you have the rest of the project set up: a bundler/builder like Vite, your dependencies installed, and an index.html file that imports this JavaScript. They also assume that you have your proxy set up, as well as everything else necessary to complete a full workflow.
Primary app
import { createIdvFlow } from "@microblink/platform-sdk/vanilla";
createIdvFlow({
enableD2D: true,
mode: "classic",
apiConfig: {
url: 'https://your.proxy.example/v1/transaction',
workflowId: '68306f141147ea0629a896e8',
d2d: { runAddress: 'https://your.2nd.web.app' },
},
consentData: {
userId: 'unique ID, must be collected from end user',
note: "",
givenOn: new Date().toISOString(),
isTrainingAllowed: true,
isProcessingStoringAllowed: true,
}
});
Secondary app
import { createIdvFlow } from "@microblink/platform-sdk/vanilla";
const urlSearchParams = new URLSearchParams(window.location.search);
const data = urlSearchParams.get("sdk");
const jsonString = atob(data);
const result = JSON.parse(jsonString);
createIdvFlow({
mode: "d2d",
apiConfig: {
apiUrl: result.apiAddress,
transactionId: result.transactionId,
ephemeralKey: result.ephemeralKey,
d2d: { joinKey: result.deviceJoinKey },
},
});
Summary
To summarize, in the examples above, the primary app will start the identity verification flow, collect the end-user's consent, and send this data to your proxy. The proxy will authenticate the request, and will contact the Microblink back end. It will then return the instructions on how to continue with the transaction to the primary web app.
The primary web app will pack this up into a QR code (link).
This link will be directed to your runAddress (in the example above it's https://your.2nd.web.app).
The data on how to continue with the transaction will be base64-encoded and passed as a query parameter (?sdk=).
When the user opens that link, they will open the secondary web app.
The secondary web app is configured to read the URL parameters.
It will search for an sdk query parameter, and extract information from it.
It will then pass this information to its own apiConfig object, and resume the same transaction.
The user will complete the steps that you've defined in your workflow. Upon completion, the user will be redirected back to the primary app, where they will see a message signalling their completion status (success or failure).