Receiving messages from nRF Cloud
This guide explains how to receive messages from nRF Cloud using the Message Routing Service. It walks you through the steps to create an HTTP server using Node.js and Express, and how to securely process messages sent from your team.
The Message Routing Service uses HTTP POST requests to send messages from devices on your team to your server.
Prerequisites and requirements
Make sure the following prerequisites and requirements are met before you proceed:
- Have an nRF Cloud account.
- Have an Owner or Admin role in your team.
- Have one or more devices added to your team.
- Have basic knowledge of programming.
- An environment to run your server code (local machine or cloud service).
- Ability to expose your server to the Internet (using tools like ngrok for local development).
- Ability to make HTTP requests (using tools like curl).
Setting up the server
This section explains how to set up an HTTP server.
Using Node.js and Express
The following example uses Node.js and Express to set up an HTTP server:
-
Download and install Node.js from the official website.
-
Initialize your project:
mkdir destination-servercd destination-server -
Create
package.json:{"name": "webhook-server","version": "1.0.0","description": "Example destination for nRF Cloud Message Routing Service","main": "webhook-server.js","author": "Nordic Semiconductor","license": "ISC","dependencies": {"express": "^4.21.0","body-parser": "^1.20.0"}} -
Create
server.js.The following is an example of a simple Node.js server that:
- Receives webhook requests.
- Optionally verifies the authenticity of the message using the one or more
of the
x-api-keyandx-nrfcloud-signatureheaders. - Sets the HTTP status code to 200 if authenticated or 401 if not.
- Optionally sets the
x-nrfcloud-team-idheader to the team ID.
The example reads a self-signed certificate for HTTPS communication. You can create such a certificate with (for example) a Linux command:
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -keyout private-key.pem -out certificate.pemThis example uses Express, a popular web framework for Node.js, and the crypto module for signature verification.
Change the lines under each "Set true to use this feature" and "Replace this with..." comment lines to reflect your use case and environment.
// Example webhook destination for nRF Cloud Message Routing Serviceconst express = require("express");const bodyParser = require("body-parser");const crypto = require("crypto");const https = require("https");const fs = require("fs");const app = express();const port = 8000;// Set true to use this featureconst useApiKeyAuthentication = false;// Set true to use this featureconst useSignatureAuthentication = false;// Set true to use this featureconst useTwoStepVerification = false;// Replace this with your token if using API key authenticationconst token = "myToken";// Replace this with your secret key if using signature authenticationconst secretKey = "mySecretKey";// Replace this with your nRF Cloud team ID if NOT using two step verificationconst teamId = "8da963d3-f0f0-432d-a667-20bfdc0f314e";// Will be assigned at each message receivedlet statusCode;let returnMessage;// Verify the API key in the request matches your tokenconst verifyApiKey = (req) => {const reqToken = req.headers["x-api-key"];const verified = reqToken === token;if (!verified) {statusCode = 401;returnMessage = "Our token does not match API key in header";}return verified; // true or false};// Verify the signature in the request, using your secret keyconst verifySignature = (req) => {const signature = req.headers["x-nrfcloud-signature"];const body = JSON.stringify(req.body);// Create HMAC hex digestconst hmac = crypto.createHmac("sha256", secretKey);hmac.update(body, "utf8");const digest = hmac.digest("hex");const verified = digest === signature;if (!verified) {statusCode = 401;returnMessage = "HMAC digest does not match header signature";}return verified; // true or false};app.use(bodyParser.json());app.post("/", (req, res) => {console.log("Got a POST to /, request contains:");console.log({headers: req.rawHeaders,url: req.url,method: req.method,params: req.params,query: req.query,body: JSON.stringify(req.body, null, 2),});let valid = true;if (useApiKeyAuthentication) {valid = verifyApiKey(req);}if (useSignatureAuthentication) {valid = verifySignature(req);}if (valid) {// Your logic here - process the requeststatusCode = 200;returnMessage = "Webhook POST request processed successfully";}// Finish processingif (!useTwoStepVerification) {res.set("x-nrfcloud-team-id", teamId);}res.status(statusCode).send(returnMessage);console.log("Response:", returnMessage);console.log({ statusCode: res.statusCode, headers: res.getHeaders() });});const options = {key: fs.readFileSync("private-key.pem"),cert: fs.readFileSync("certificate.pem"),};https.createServer(options, app).listen(port, () => {console.log(`Webhook running, listening on port ${port}`);}); -
Install dependencies:
npm i -
Run the server:
node server.js -
Expose to the Internet (development only):
ngrok http 8000
Use the provided https URL as your URL endpoint in nRF Cloud when you create a
destination.
Setting up the HTTP destination in nRF Cloud
Complete the following steps to set up a new HTTP destination:
-
Log in to the nRF Cloud portal.
-
Select Device Management in the left navigation bar.
A panel opens to the right.
-
Select Message Routing Service.
-
Create a new HTTP destination:
-
Click Add Destination.
-
Enter the URL provided by
ngrokor your server's public URL (for example,https://your-ngrok-url.ngrok.io/webhook). -
Add an API token, secret, or both, depending on your changes to the
server.jsfile.- For the above example, since it uses a self-signed certificate, turn off
the
Verify SSLfeature.
- For the above example, since it uses a self-signed certificate, turn off
the
-
Click Create Destination.
-
Verifying your destination
If you edited your server.js script to change useTwoStepVerification to
true, you must manually verify your destination, using either the portal or
the REST API. See the verification sections of
Using the nRF Cloud Message Routing Service for details.
Testing your destination
You can test your destination using the nRF Cloud portal as follows:
- Navigate to Message Routing.
- Click the icon in the Test column for your newly created destination. This sends a test message to your destination.
Testing API key authentication
If you edited your server.js script to change useApiKeyAuthentication to
true and entered your token in the file, you can test the API key
authentication feature.
After sending the test message described above, look for the x-api-key header
in your server's message response. It should match the API key token you entered
when creating your destination in nRF Cloud, and the token in your
server.js.
Testing signature authentication
If you changed useSignatureAuthentication to true by editing your
server.js script, and entered your secretKey in the file, you can test the
signature authentication feature.
Sending a request with an incorrect signature using curl
Use the following curl command to send a request with an incorrect signature
to your server:
curl -X POST -H "Content-Type: application/json" \
-H "x-nrfcloud-signature: incorrectsignature" \
-d '{
"type": "device.messages",
"timestamp": "2024-09-05T21:59:47.323Z",
"messages": [
{
"teamId": "test-team",
"deviceId": "test-device",
"messageId": "test-message",
"receivedAt": "2024-09-05T21:59:44.714Z",
"topic": "test/topic",
"message": {
"appId": "TEST",
"messageType": "DATA",
"data": "test data"
}
}
]
}' \
https://your-destination-url.com/webhook
Expected response:
The server responds with 401 Unauthorized and the message Invalid signature.
Sending a request with the correct signature
Instead of manually computing the signature, you can use the Test feature in nRF Cloud to send a test message to your destination. This test message includes the correct signature, allowing you to verify that your server accepts requests with a valid signature.
After sending the test message described above, review your server's message response. Verify that the message was received and that the signature was validated successfully.
Start receiving device messages
Now that you have tested the HTTP server and destination in nRF Cloud, you are ready to start receiving messages from your team's devices. MRS will not send messages to your destination until it has been verified.
Once the devices on your team begin sending messages to nRF Cloud, verify that they are also sent to your destination.