Skip to main content

Authorization

Enterprise Eventing uses two distinct authorization mechanisms: Service Account tokens for making API requests to SmartThings, and HTTP Signatures for verifying webhook deliveries from SmartThings.

API Authentication

To create and manage sinks and subscriptions, your application authenticates using Service Account credentials.

Service Accounts

Service Accounts provide a way for your applications to authenticate with SmartThings APIs programmatically, without using a person's login credentials. See the Service Accounts documentation for complete details on:

Required Permissions

Access to Enterprise Eventing APIs is controlled by Service Account roles. Assigning the correct role to your Service Account grants the necessary OAuth scopes to your application.

For Account-level Sinks:

  • Account Admin (ACCOUNT_ADMIN) - Required for creating and managing account-level sinks.

For Subscriptions:

  • Account Admin (ACCOUNT_ADMIN) - Required for creating and managing account subscriptions.

Making API Requests

Include your Service Account's bearer token in the Authorization header:

curl -X POST https://enterprise.smartthings.com/accounts/{accountId}/sinks \
-H 'Authorization: Bearer YOUR_SERVICE_ACCOUNT_TOKEN' \
-H 'Accept: application/vnd.smartthings+json;v=2' \
-H 'Content-Type: application/json' \
-d '{
"name": "My-Webhook-Endpoint",
"type": "HTTPS_SINK",
"httpsSink": {
"endpoint": "https://example.com/webhook"
}
}'

Sink Verification

When you create a sink, SmartThings sends a SINK_CONFIRMATION challenge to your webhook endpoint to verify that you control the target URL. Your endpoint must respond with a 200 OK and a JSON body containing the original challenge value.

Example Challenge Request:

{
"accountId": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"notificationType": "SINK_CONFIRMATION",
"version": "2",
"sinkConfirmationNotification": {
"sinkId": "7de9a66a-8be6-4b69-9543-92ab3058bd6d",
"challenge": "550e8400-e29b-41d4-a716-446655440000"
}
}

Required 200 OK Response:

{
"challenge": "550e8400-e29b-41d4-a716-446655440000"
}

If the challenge is not completed, the sink will not be activated, and no events will be delivered.

Webhook Signature Verification

When SmartThings delivers events to your webhook, the request is digitally signed using HTTP Signatures to prevent tampering and replay attacks.

Why Verify Signatures?

Although verifying signatures is optional, it's highly recommended to:

  • Confirm the request originated from SmartThings
  • Detect man-in-the-middle attacks
  • Prevent replay attacks
  • Verify the request body hasn't been tampered with

Signature Format

SmartThings signs webhook requests using the HTTP Signatures RFC specification. The signature appears in the Authorization header:

Authorization: Signature
keyId="/pl/useast1/a1b2c3d4-e5f6-7890-1234-567890abcdef"
headers="(request-target) digest date"
algorithm="rsa-sha256"
signature="PS/XfElOxcA9PmD08l6Mr2Igporse8cqZKy+OKyRa4Basu/J7YetQdQnC/bV9bnd4WXV3..."

Signature Components

  • keyId - URI path to retrieve SmartThings' public key for verification
  • headers - List of headers included in the signature (in order)
  • algorithm - Signing algorithm (rsa-sha256)
  • signature - The actual signature to verify

Signed Headers

SmartThings signatures include these headers:

  1. (request-target) - Synthetic header combining HTTP method and URI path
    • Format: post /your/webhook/path (lowercase)
    • Not an actual HTTP header - computed for signing only
  2. digest - SHA-256 digest of the request body
    • Verifies the body hasn't been modified
  3. date - Request timestamp
    • Prevents replay attacks (reject old signatures)

Retrieving the Public Key

SmartThings hosts public keys at:

https://key.smartthings.com/key/{keyId}

Append the keyId from the signature to retrieve the RSA public key.

Key Rotation and Caching

SmartThings public keys rotate regularly. To ensure your verification logic continues to work after a rotation, you must fetch keys dynamically using the keyId from the signature.

For performance, it is recommended to cache the public keys. A good strategy is:

  • Use the keyId as your cache key.
  • When a webhook arrives, check your cache for the keyId.
  • If the key is not in your cache (a cache miss), fetch it from https://key.smartthings.com/key/{keyId} and store it in your cache with a short Time-To-Live (TTL), such as a few hours.

Do not cache keys indefinitely. A short TTL ensures you will automatically pick up new keys after a rotation.

Verification Steps

  1. Parse the Authorization header to extract signature components
  2. Fetch the public key from https://key.smartthings.com/key/{keyId}
  3. Reconstruct the signing string from the specified headers
  4. Verify the signature using the public key

Example: Verification Pseudocode

function verifyWebhookSignature(request) {
// 1. Parse Authorization header
const signature = parseAuthorizationHeader(request.headers['authorization']);

// 2. Fetch SmartThings public key
const publicKey = fetchPublicKey(`https://key.smartthings.com/key/${signature.keyId}`);

// 3. Reconstruct signing string
const signingString = buildSigningString(request, signature.headers);

// 4. Verify signature
const isValid = verifyRSASignature(signingString, signature.signature, publicKey);

if (!isValid) {
throw new Error('Invalid signature');
}

// 5. Check date freshness (prevent replay attacks)
const requestDate = new Date(request.headers['date']);
const now = new Date();
const ageMinutes = (now - requestDate) / 1000 / 60;

if (ageMinutes > 5) {
throw new Error('Signature too old');
}

return true;
}

Security Best Practices

For API Requests

  • Rotate API keys regularly - Generate new keys and disable old ones
  • Secure token storage - Never commit tokens to version control
  • Use HTTPS only - All API requests must use TLS

For Webhook Security

  • Always use HTTPS - Webhooks must have valid SSL certificates
  • Verify signatures - Implement signature verification to prevent attacks
  • Validate request freshness - Reject signatures older than 5 minutes
  • Be idempotent - Handle duplicate event deliveries gracefully
  • Log security events - Track failed signature verifications

Rate Limiting and Retries

If your webhook endpoint fails to respond with a 2xx status, SmartThings will automatically retry the delivery to handle transient network issues. Because retries can result in duplicate event deliveries, it is critical that your webhook is idempotent.

Ensure your webhook responds quickly (< 5 seconds) to avoid timeouts.

Troubleshooting

401 Unauthorized on API Requests

  • Verify your Service Account token hasn't expired
  • Confirm the Service Account has the required role assignments
  • Check the Accept header includes the correct version (e.g., application/vnd.smartthings+json;v=2).

Webhook Signature Verification Failures

  • Ensure you're fetching the public key dynamically (don't cache indefinitely)
  • Verify the signing string matches exactly (including order of headers)
  • Check that (request-target) is lowercase and properly formatted
  • Confirm the request date header is recent (< 5 minutes old)

Next Steps