salesforce-security-basics

Installation
SKILL.md

Salesforce Security Basics

Overview

Security best practices for Salesforce integrations: Connected App configuration, OAuth scope management, field-level security, and credential rotation.

Prerequisites

  • Salesforce org with System Administrator access
  • Connected App created in Setup > App Manager
  • Understanding of Salesforce security model (Profile, Permission Set, OWD)

Instructions

Step 1: Secure Connected App Configuration

Setup > App Manager > New Connected App:

1. Enable OAuth Settings
2. Callback URL: https://yourapp.com/oauth/callback (NOT localhost in prod)
3. Selected OAuth Scopes — USE MINIMUM REQUIRED:
   - "Manage user data via APIs (api)" — for REST/SOQL access
   - "Perform requests at any time (refresh_token, offline_access)" — for refresh tokens
   - DO NOT add "Full access (full)" unless absolutely necessary

4. Require Proof Key for Code Exchange (PKCE): Enable for public clients
5. Require Secret for Web Server Flow: Enable
6. IP Relaxation: "Enforce IP restrictions" (not "Relax IP restrictions")

Step 2: Credential Storage

# .env (NEVER commit to git)
SF_LOGIN_URL=https://login.salesforce.com
SF_USERNAME=integration-user@yourcompany.com
SF_PASSWORD=<from-vault>
SF_SECURITY_TOKEN=<from-vault>
SF_CLIENT_ID=<connected-app-consumer-key>
SF_CLIENT_SECRET=<connected-app-consumer-secret>

# .gitignore — ALWAYS include
.env
.env.local
.env.*.local
server.key    # JWT private key
*.pem
*.key

Step 3: Use a Dedicated Integration User

Create a dedicated Salesforce user for API access:

1. Profile: Create "API Integration" profile (clone from Standard User)
   - Login Hours: restrict to expected operating hours
   - Login IP Ranges: restrict to your server IPs
   - Object permissions: ONLY objects your integration needs

2. Permission Set: "Integration API Access"
   - Object: Account — Read, Create, Edit (no Delete)
   - Object: Contact — Read, Create, Edit (no Delete)
   - Field-Level Security: only expose fields the integration reads/writes

3. NEVER use a System Administrator user for integrations

Step 4: Field-Level Security (FLS) Enforcement

// Always check FLS before operations — especially for managed packages
const conn = await getConnection();
const meta = await conn.sobject('Account').describe();

// Check if field is accessible (readable)
const industryField = meta.fields.find(f => f.name === 'Industry');
if (!industryField?.accessible) {
  throw new Error('Industry field is not accessible — check FLS');
}

// Check if field is updateable (writable)
if (!industryField?.updateable) {
  console.warn('Industry field is read-only for this user');
}

// Check which fields the current user can actually see
const accessibleFields = meta.fields
  .filter(f => f.accessible)
  .map(f => f.name);
console.log('Accessible fields:', accessibleFields.length);

Step 5: Security Token Rotation

# Salesforce security tokens auto-reset when password changes
# Rotation procedure:
# 1. Setup > My Personal Information > Reset My Security Token
# 2. New token is emailed to the user
# 3. Update SF_SECURITY_TOKEN in your vault/env
# 4. Verify connection works with new token
# 5. For JWT: rotate the certificate in the Connected App

# Automate rotation check
sf org display --target-org integration-user --json | jq '.result.accessToken'

Step 6: Audit Logging

// Query Setup Audit Trail for security events
const auditTrail = await conn.query(`
  SELECT CreatedDate, CreatedBy.Username, Action, Section, Display
  FROM SetupAuditTrail
  WHERE CreatedDate >= LAST_N_DAYS:7
    AND (Section = 'Connected Apps' OR Section = 'Users' OR Section = 'Profiles')
  ORDER BY CreatedDate DESC
  LIMIT 50
`);

for (const entry of auditTrail.records) {
  console.log(`${entry.CreatedDate} | ${entry.CreatedBy?.Username} | ${entry.Action} | ${entry.Display}`);
}

Security Checklist

  • Connected App uses minimum OAuth scopes (not full)
  • Dedicated integration user (not admin)
  • IP restrictions on Connected App and user profile
  • Credentials in vault/env vars, never in code
  • .env and *.key files in .gitignore
  • Field-Level Security restricts sensitive fields
  • Security token rotated regularly
  • Setup Audit Trail monitored
  • PKCE enabled for public clients

Error Handling

Security Issue Detection Mitigation
Exposed credentials in git git log -p --all -S 'SF_PASSWORD' Rotate immediately, use git-secrets
Overprivileged user Check profile permissions Create restricted integration profile
Missing FLS Describe call shows accessible: false Update Permission Set
IP not whitelisted LOGIN_MUST_USE_SECURITY_TOKEN Add IP to login IP ranges

Resources

Next Steps

For production deployment, see salesforce-prod-checklist.

Weekly Installs
1
GitHub Stars
2.1K
First Seen
Mar 25, 2026