intercom-security-basics
'Apply Intercom security best practices for tokens, webhook verification,
Allowed Tools
Provided by Plugin
intercom-pack
Claude Code skill pack for Intercom (24 skills)
Installation
This skill is included in the intercom-pack plugin:
/plugin install intercom-pack@claude-code-plugins-plus
Click to copy
Instructions
Intercom Security Basics
Overview
Security best practices for Intercom access tokens, webhook signature
verification, Identity Verification (HMAC), and least-privilege OAuth scopes.
The full code for each control lives in references/ so this file stays a fast,
high-level checklist you can follow end-to-end, then drill into for depth:
- Implementation reference — complete webhook,
identity, rotation, and scope code.
- Worked examples — four end-to-end walkthroughs.
Prerequisites
- Intercom access token or OAuth credentials
- Understanding of HMAC cryptographic signatures
- Access to Intercom Developer Hub
Instructions
Step 1: Secure Token Storage
Store every secret in .env (or a secret manager) and never commit it.
# .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
Then scan history for anything already leaked — use Grep (or the shell) to
search committed content for token markers:
git log --all -p | grep -i "INTERCOM_ACCESS_TOKEN\|dG9r" | head -5
# If found: rotate the token immediately, then use git-filter-repo to remove it.
Step 2: Webhook Signature Verification (X-Hub-Signature)
Intercom signs webhook notifications with HMAC-SHA1 using X-Hub-Signature.
Verify it on every incoming webhook against the raw request body, using a
timing-safe comparison, and reject mismatches with 401:
const expectedSignature = "sha1=" + crypto
.createHmac("sha1", secret)
.update(payload) // payload = raw Buffer, not parsed JSON
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
Full Express handler: implementation.md — Webhook Signature Verification.
Step 3: Identity Verification (User Hash)
Identity Verification blocks impersonation by requiring an HMAC-SHA256 of the
user's identifier, generated server-side only:
crypto.createHmac("sha256", process.env.INTERCOM_IDENTITY_SECRET!)
.update(userId)
.digest("hex");
Return this userhash alongside appid and user_id for Messenger boot. Full
code: implementation.md — Identity Verification.
Step 4: Least-Privilege OAuth Scopes
Only request the scopes your app actually uses — excess scopes widen the blast
radius of a leaked token. The full use-case → scope mapping is in
implementation.md — Least-Privilege OAuth Scopes.
For example, a read-only contacts integration needs just Read contacts, not
full CRM read/write.
Step 5: Token Rotation Procedure
Rotate by adding the new token to your secret manager and deploying before
revoking the old one, so no window exists without a live token. Full procedure
(AWS / GCP / Vault examples + verification curl): implementation.md — Token Rotation Procedure.
Output
Applying this skill produces:
- A
.env(or secret-manager entry) holdingINTERCOMACCESSTOKEN,
INTERCOMWEBHOOKSECRET, and INTERCOMIDENTITYSECRET, with .env patterns
added to .gitignore.
- A webhook route that returns
200for validX-Hub-Signaturedeliveries and
401 for missing or forged signatures.
- Server-side
user_hashgeneration wired into the Messenger boot settings. - An OAuth app requesting only least-privilege scopes.
- A documented, tested token-rotation runbook.
The end state is the completed Security Checklist below, every box ticked.
Security Checklist
- [ ] Access tokens stored in environment variables or secret manager
- [ ]
.envfiles in.gitignore - [ ] Different tokens for dev/staging/production workspaces
- [ ] Webhook signatures verified on every request (X-Hub-Signature)
- [ ] Identity Verification enabled (user_hash)
- [ ] OAuth scopes are minimal (least privilege)
- [ ] Token rotation procedure documented and tested
- [ ] Git history scanned for leaked credentials
- [ ] HTTPS enforced for all webhook endpoints
Error Handling
| 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 |
Examples
Four end-to-end walkthroughs live in references/examples.md:
- Secure a fresh integration from zero — store the three secrets in
.env
and prove none are staged.
- Scan an existing repo for a leaked token —
git log --all -p | grepfor
token markers before shipping.
- Add webhook verification to an Express app — reject forged payloads with
401 via X-Hub-Signature.
- Turn on Identity Verification for the Messenger — server-side
user_hash
to stop impersonation.
Quick sanity check that a rotated token is live:
curl -s https://api.intercom.io/me \
-H "Authorization: Bearer $NEW_TOKEN" | jq '.type'
# Should return "admin"
Resources
Next Steps
For production deployment hardening beyond these basics, see the
intercom-prod-checklist skill, which covers rate limiting, error monitoring,
and staged rollout for the same integration.