From intercom-pack
Secures Intercom integrations with token storage best practices, HMAC-SHA1 webhook verification in Node.js/Express, identity hashes, and minimal OAuth scopes.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin intercom-packThis skill is limited to using the following tools:
Security best practices for Intercom access tokens, webhook signature verification, Identity Verification (HMAC), and least-privilege OAuth scopes.
Applies HubSpot security best practices: least-privilege scopes, private app token storage/validation, and v3 webhook signature verification with HMAC SHA-256.
Configures Intercom workspaces for dev, staging, prod with TypeScript configs, per-environment tokens, webhooks, and secret management via AWS/GCP/Vault.
Secures Attio API integrations via least-privilege token scoping, platform secret management, webhook verification, and rotation procedures.
Share bugs, ideas, or general feedback.
Security best practices for Intercom access tokens, webhook signature verification, Identity Verification (HMAC), and least-privilege OAuth scopes.
# .env (NEVER commit to git)
INTERCOM_ACCESS_TOKEN=dG9rOmFiY2RlZmdoaQ==
INTERCOM_WEBHOOK_SECRET=your-webhook-signing-secret
INTERCOM_IDENTITY_SECRET=your-identity-verification-secret
# .gitignore (mandatory entries)
.env
.env.local
.env.*.local
Verify no tokens are committed:
# Scan git history for leaked tokens
git log --all -p | grep -i "INTERCOM_ACCESS_TOKEN\|dG9r" | head -5
# If found: rotate token immediately, then use git-filter-repo to remove
Intercom signs webhook notifications with HMAC-SHA1 using X-Hub-Signature. You must verify this on every incoming webhook.
import crypto from "crypto";
import express from "express";
function verifyIntercomWebhook(
payload: Buffer,
signature: string,
secret: string
): boolean {
// Intercom uses X-Hub-Signature with HMAC-SHA1
const expectedSignature = "sha1=" + crypto
.createHmac("sha1", secret)
.update(payload)
.digest("hex");
// Timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
const app = express();
app.post(
"/webhooks/intercom",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.headers["x-hub-signature"] as string;
if (!signature) {
return res.status(401).json({ error: "Missing signature" });
}
if (!verifyIntercomWebhook(req.body, signature, process.env.INTERCOM_WEBHOOK_SECRET!)) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(req.body.toString());
// Process verified webhook...
res.status(200).json({ received: true });
}
);
Intercom Identity Verification prevents impersonation by requiring an HMAC of the user's identifier.
import crypto from "crypto";
// Server-side: generate user hash
function generateIntercomUserHash(userId: string): string {
return crypto
.createHmac("sha256", process.env.INTERCOM_IDENTITY_SECRET!)
.update(userId)
.digest("hex");
}
// Pass to frontend for Messenger initialization
app.get("/api/intercom-settings", (req, res) => {
const userId = req.user.id;
res.json({
app_id: process.env.INTERCOM_APP_ID,
user_id: userId,
user_hash: generateIntercomUserHash(userId),
});
});
Only request scopes your app actually needs:
| Use Case | Required Scopes |
|---|---|
| Read contact data only | Read contacts |
| Manage conversations | Read conversations, Write conversations |
| Send messages | Write messages |
| Manage Help Center | Read articles, Write articles |
| Full CRM integration | Read/write contacts, Read/write conversations, Read/write tags |
# 1. Generate new token in Developer Hub
# Settings > Developer Hub > Your App > Authentication
# 2. Update in secret manager (examples)
# AWS
aws secretsmanager update-secret \
--secret-id intercom/access-token \
--secret-string "new_token_here"
# GCP
echo -n "new_token_here" | gcloud secrets versions add intercom-token --data-file=-
# Vault
vault kv put secret/intercom access_token="new_token_here"
# 3. Verify new token
curl -s https://api.intercom.io/me \
-H "Authorization: Bearer $NEW_TOKEN" | jq '.type'
# Should return "admin"
# 4. Deploy updated config
# 5. Revoke old token in Developer Hub
.env files in .gitignore| Security Issue | Detection | Mitigation |
|---|---|---|
| Leaked token in git | git log -p | grep dG9r | Rotate immediately, remove from history |
| Invalid webhook signature | 401 from verification | Check secret matches Developer Hub |
| Missing Identity Verification | Intercom dashboard warning | Implement user_hash on server |
| Excessive OAuth scopes | Scope audit | Remove unnecessary scopes |
| Token never rotated | Age tracking | Schedule quarterly rotation |
For production deployment, see intercom-prod-checklist.