跳到主要内容

Challenge-Response Provisioning

Securely map a device to the user's account using cloud-verified cryptography before Wi-Fi credentials are sent.

信息

Default since SDK v2.3.0. ESPDevice.provision() uses this flow automatically. Pass ProvisionType.MQTT for the legacy flow.

信息

A provisioning adapter is required. See Provisioning and Adapters.

备注

The userInstance refers to ESPRMUser from User Sign in.

What This Module Does ?

Challenge-response verifies device ownership before Wi-Fi setup: the cloud issues a challenge, the device signs it over BLE, the cloud verifies—then credentials are sent.

Use the defaultdevice.provision() without overrides. Pass ProvisionType.CHAL_RESP to be explicit. Pass ProvisionType.MQTT only for devices without ch_resp capability.

Most apps only need the default provision() call plus MQTT fallback when challenge-response is unsupported. See User-Node Mapping for product concepts.

Expected outcome: Device is verified, mapped to the user, receives Wi-Fi, and appears in getUserNodes().

Common Workflows

import { ProvisionType } from "@espressif/rainmaker-base-sdk";

await device.provision(ssid, passphrase, onProgress);

With group:

await device.provision(ssid, passphrase, onProgress, groupId, ProvisionType.CHAL_RESP);

Legacy MQTT (older devices)

await device.provision(ssid, passphrase, onProgress, undefined, ProvisionType.MQTT);

Detect capability and fall back

import { ChallengeResponseHelper, ProvisionType } from "@espressif/rainmaker-base-sdk";

const versionInfo = await device.getDeviceVersionInfo();
const supported = ChallengeResponseHelper.checkChallengeResponseCapability(versionInfo);

if (supported) {
await device.provision(ssid, passphrase, onProgress);
} else {
await device.provision(ssid, passphrase, onProgress, undefined, ProvisionType.MQTT);
}

Error Handling

try {
await device.provision(ssid, passphrase, onProgress);
} catch (error) {
if (error.code === "CHALLENGE_RESPONSE_NOT_SUPPORTED") {
await device.provision(ssid, passphrase, onProgress, undefined, ProvisionType.MQTT);
} else {
console.error("Provisioning failed:", error);
}
}

Advanced Concepts

Mental model

Prove the device is genuine → map to user → send Wi-Fi.

Challenge-response sequence

Flow selection

Manual step-by-step control

const { challenge, request_id } = await device.initiateUserNodeMapping({});
const challengePayload = ChallengeResponseHelper.createChallengeRequest(challenge);
const responseStr = await device.sendData("ch_resp", base64Encode(challengePayload));
const deviceResponse = ChallengeResponseHelper.parseAndValidateDeviceResponse(
base64Decode(responseStr)
);

await device.verifyUserNodeMapping({
request_id,
node_id: deviceResponse.nodeId,
challenge_response: deviceResponse.signedChallenge,
});
await device.setNetworkCredentials(ssid, passphrase);

Best Practices

  1. Use default provision() — avoid manual steps unless required
  2. MQTT fallback only when needed
  3. Handle CHALLENGE_RESPONSE_NOT_SUPPORTED with clear user messaging
  4. Pass groupId in the same call when adding to a group

On this page