Hosting a WebHook endpoint

This document describes how to create a WebHook SmartApp.

Steps

  1. Create a web services application that can receive incoming HTTP POST requests to a publicly accessible endpoint via HTTPS. You can write and host your application using the language and tools of your choice.
  2. When creating your SmartApp, specify the endpoint URL of your app as the target URL, and select WEBHOOK as the app type. Your SmartApp must be reachable by SmartThings at this time, as it will be called with the PING lifecycle to verify its existence and health.
  3. Store the public key returned after creating your SmartApp. This will be used to verify incoming requests are sent from SmartThings.
  4. Ensure that all subsequent incoming requests are verified as coming from SmartThings, as documented below.

Authorizing calls from SmartThings

HTTP Signatures

All requests sent by SmartThings are digitally signed in accordance with the IETF HTTP Signatures Draft 3 specification. A full discussion of HTTP signature verification is beyond the scope of this document; consult the specification referenced above, or see Joyent's page on http signing for more information.

Authorization Flow

Currently, SmartThings provides 2 mechanisms for which signatures are generated.

  • Using the public / private key generated during SmartApp registration.
  • Using a publicly available SmartThings generated x.509 certifcate.

The following diagram outlines the general flow for both signing mechanisms.

alt text

  1. Request made by SmartThings to your SmartApp.
    
     Authorization: Signature keyId="<aKeyId>",signature="<aDigitalSignature>",headers="<aHeadersSet>",algorithm="<aSigningAlgorithm>"
    
  2. Depending on the elected signing mechanism (SmartApp Public Key or SmartThings x.509 Certificate), the keyId field in the Authorization header will vary.
    • If SmartThings Public Key ⟶ Fetch public key via the mechanism you implemented to store. This is same public key provided during registration.
    • If SmartThings x.509 ⟶ SmartApp should call https://key.smartthings.com + <aKeyId> to fetch the correct public key for signature verification.
  3. SmartApp computes the validity of the signature using the resolved key combined with the HTTP Headers provided on callback request.

Using SmartApp Public Key

Using the SmartApp's public key is the current default approach for SmartThings callback authorization.

This mechanism requires you to copy the public key you received during SmartApp registration into your SmartApp container, and use it to verify that the signature provided on the Authorization header originated from SmartThings.

Using SmartThings x.509 Certificate

Alternatively, a SmartApp can opt in to have requests digitally signed by one of the publicly available SmartThings x.509 certificates.

This approach has the following benefits:

  • Increased security as the certificates are rotated periodically.
  • Ease of use. You are no longer required to deploy copies of your SmartApp's public key alongside your integration.

Opt in your SmartApp

To opt into using the SmartThings x.509 certificate for digital signing, make a simple API call.

You will need a Personal Access Token and your SmartApp's App ID, which can be found in Developer Workspace.

Request

curl --request PUT \
--url https://api.smartthings.com/apps/${YOUR_APP_ID}/signature-type \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${PAT_TOKEN}" \
--data '{ "signatureType": "ST_PADLOCK" }' 

Response

202 {}

Additionally, a SmartApp can revert back to using the associated public key:

Request

curl --request PUT \
--url https://api.smartthings.com/apps/${YOUR_APP_ID}/signature-type \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${PAT_TOKEN}" \
--data '{ "signatureType": "APP_RSA" }' 

Response

202 {}

The request to change the signature type of your SmartApp is processed asynchronously. It may take up to a few minutes for the change to fully take effect.

Example

The recommended and easiest way to implement the callback authorization logic in your SmartApp is to use one of the official SDKs.

Currently SDKs are available for both NodeJs and Java ecosystems. They can be found on Github @:

The following uses the SmartThings Node SDK.



/**
 * A very simple SmartApp example leveraging the SDK
 * to launch a SmartApp on the Express web framework.
 *
 * All SmartThings callback authorization mechanisms 
 * are implicitly supported through SDK usage.
 */
const express = require(&#39;express&#39;);
const SmartApp = require(&#39;@smartthings/smartapp&#39;);
const server = express();
const PORT = 5555;

server.use(express.json());

const smartapp = new SmartApp()
// If you do not have it yet, omit publicKey() - i.e. PING lifecycle
// Usage of &#39;@&#39; symbol informs SDK to fetch from local disk using `fs` package.
//  .publicKey(&#39;@smartthings_rsa.pub&#39;)
    .enableEventLogging(2)
    .page(&#39;mainPage&#39;, (context, page, configData) =&gt; {
        page
            .name(&#39;SmartApp Authorization Example&#39;)
            .complete(true)
            .section(&#39;my-section&#39;, section =&gt; {
                section
                    .paragraphSetting(&#39;my-paragraph&#39;)
                    .text(&#39;SmartApp Authorization Example&#39;)
                    .description(&#39;An example of how to authorize incoming SmartThings requests to your SmartApp.&#39;)

            })
    });

server.post(&#39;/&#39;, (req, res, next) =&gt; {
    console.log(req.header(&#39;Authorization&#39;));
    smartapp.handleHttpCallback(req, res)
});

server.listen(PORT, () =&gt; console.log(`Server is up and running on port ${PORT}`));

See also