Skills Development Securing Salesforce Integrations Best Practices

Securing Salesforce Integrations Best Practices

v20260423
salesforce-security-basics
A comprehensive guide detailing best practices for securing Salesforce integrations and API access. It covers configuring Connected Apps with minimum OAuth scopes, implementing least privilege access, establishing dedicated integration users, and enforcing Field-Level Security (FLS). Essential knowledge for robust API development, security audits, and maintaining data integrity within the Salesforce ecosystem.
Get Skill
92 downloads
Overview

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 IssueDetectionMitigation
Exposed credentials in gitgit log -p --all -S 'SF_PASSWORD'Rotate immediately, use git-secrets
Overprivileged userCheck profile permissionsCreate restricted integration profile
Missing FLSDescribe call shows accessible: falseUpdate Permission Set
IP not whitelistedLOGIN_MUST_USE_SECURITY_TOKENAdd IP to login IP ranges

Resources

Next Steps

For production deployment, see salesforce-prod-checklist.

Info
Category Development
Name salesforce-security-basics
Version v20260423
Size 5.81KB
Updated At 2026-04-28
Language