Claude-code-plugins-plus-skills salesloft-security-basics
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/salesloft-pack/skills/salesloft-security-basics" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-salesloft-security-basics && rm -rf "$T"
manifest:
plugins/saas-packs/salesloft-pack/skills/salesloft-security-basics/SKILL.mdsource content
SalesLoft Security Basics
Overview
Secure SalesLoft API integrations: OAuth token management, webhook signature verification, secret storage, and scope-based access control. SalesLoft uses OAuth 2.0 bearer tokens and HMAC-SHA256 webhook signatures.
Instructions
Step 1: Secret Storage
# .gitignore -- NEVER commit credentials .env .env.local .env.*.local # .env SALESLOFT_CLIENT_ID=app-client-id SALESLOFT_CLIENT_SECRET=app-secret SALESLOFT_WEBHOOK_SECRET=webhook-signing-secret
// Validate secrets at startup const required = ['SALESLOFT_CLIENT_ID', 'SALESLOFT_CLIENT_SECRET']; for (const key of required) { if (!process.env[key]) throw new Error(`Missing required env: ${key}`); }
Step 2: Token Lifecycle Management
// Store tokens securely with expiry tracking interface TokenStore { accessToken: string; refreshToken: string; expiresAt: number; // Unix timestamp } async function getValidToken(store: TokenStore): Promise<string> { // Refresh 5 minutes before expiry if (Date.now() > (store.expiresAt - 300) * 1000) { const refreshed = await refreshAccessToken(store.refreshToken); store.accessToken = refreshed.access_token; store.refreshToken = refreshed.refresh_token; store.expiresAt = Math.floor(Date.now() / 1000) + refreshed.expires_in; await persistTokenStore(store); // Save to DB or secret manager } return store.accessToken; }
Step 3: Webhook Signature Verification
import crypto from 'crypto'; function verifyWebhookSignature( rawBody: Buffer, signature: string, timestamp: string, secret: string, ): boolean { // Reject stale webhooks (replay attack prevention) const age = Math.abs(Date.now() / 1000 - parseInt(timestamp)); if (age > 300) return false; // 5-minute window const expected = crypto .createHmac('sha256', secret) .update(`${timestamp}.${rawBody.toString()}`) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ); }
Step 4: OAuth Scope Minimization
| Use Case | Required Scopes | Avoid |
|---|---|---|
| Read-only dashboard | , | |
| Cadence enrollment | , | |
| Full sync | , , | Team admin scopes |
Step 5: Security Checklist
- OAuth tokens stored in secret manager (not env files in prod)
- Refresh tokens encrypted at rest
- Webhook endpoints verify signatures before processing
-
files in.env.gitignore - Different OAuth apps for dev/staging/prod
- Token refresh runs before expiry (not after 401)
- API logs monitored for unusual access patterns
Error Handling
| Issue | Detection | Response |
|---|---|---|
| Token leaked in git | GitHub secret scanning alerts | Revoke immediately, rotate |
| Webhook replay attack | Timestamp > 5 min old | Reject request |
| Brute force on webhook | High 401 rate | Rate limit webhook endpoint |
Resources
Next Steps
For production deployment, see
salesloft-prod-checklist.