Integration

Web Server Flow

Authorization Code Grant

Best for:
  • Mobile applications and SPAs
  • Applications that cannot securely store client secrets
  • JavaScript applications running in browsers
Security level : very high (5/5)

Suitable for mobile apps and SPAs that cannot securely store client secrets

Important Note
  •  Starting Mobile SDK 11.0, PKCE flow is preferred for increased security in mobile applications
Implementation Steps:
Authorization Request

Redirect user to Salesforce with response_type=token

 
User Authentication

User logs in and grants permissions

Token Return

Access token returned in URL fragment

 
Flow endpoint

Authorization:

https://mycompany.my.salesforce.com/services/auth/idp/metadata

Authorization:

https://login.salesforce.com/services/oauth2/token

Web Server Flow Example

// Step 1: Authorization URL
const authUrl = `https://login.salesforce.com/services/oauth2/authorize?` +
  `response_type=code&` +
  `client_id=${clientId}&` +
  `redirect_uri=${encodeURIComponent(redirectUri)}&` +
  `scope=full%20refresh_token`;

// Step 2: Token Exchange
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: clientId,
    client_secret: clientSecret,
    redirect_uri: redirectUri
  })
});

  

User-Agent Flow

Implicit Grant Flow

Best For:
  • Mobile applications and SPAs
  • Applications that cannot securely store client secrets
  • JavaScript applications running in browsers
Security level : Medium(3/5)

Suitable for mobile apps and SPAs that cannot securely store client secrets

Important Note:
  • Starting Mobile SDK 11.0, PKCE flow is preferred for increased security in mobile applications
Implementation Steps:
Authorization Request

Redirect user to Salesforce with response_type=tokenAccess token returned in URL fragment

User Authentication

User logs in and grants permissions

Authorization Code

Access token returned in URL fragment

Flow endpoint

Authorization:

https://mycompany.my.salesforce.com/services/auth/idp/metadata

Token:

https://login.salesforce.com/services/oauth2/token

User-Agent Flow Example

// User-Agent Flow Implementation
const authUrl = `https://login.salesforce.com/services/oauth2/authorize?` +
  `response_type=token&` +
  `client_id=${clientId}&` +
  `redirect_uri=${encodeURIComponent(redirectUri)}&` +
  `scope=api`;

// Redirect to authorization URL
window.location.href = authUrl;

// Extract token from URL fragment after redirect
function extractTokenFromUrl() {
  const hash = window.location.hash.substring(1);
  const params = new URLSearchParams(hash);
  return params.get('access_token');
}

  

JWT Bearer Token Flow

Server-to-Server Authentication

Best for:
  • Server-to-server integrations without user interaction
  • API-only applications, ETL tools, ESB systems
  • Automated backend processes
Security level : High (5/5)

Most secure server-to-server authentication using digital certificates and signed JWT

Requirements
  • X.509 certificate uploaded to Connected App
  • Proper JWT signing with private key
  • No refresh token (access token only)
Implementation Steps:
Token Request

Exchange JWT assertion for access token

Create JWT Assertion

Sign JWT with private key and required claims

API Access

Use access token for API calls

Flow endpoint

Token:

https://login.salesforce.com/services/oauth2/token

JWT Bearer Token Flow Example

// JWT Bearer Token Flow
const jwt = require('jsonwebtoken');
const fs = require('fs');

// Create JWT assertion
const privateKey = fs.readFileSync('private.key');
const payload = {
  iss: clientId,
  sub: username,
  aud: 'https://login.salesforce.com',
  exp: Math.floor(Date.now() / 1000) + 300
};

const assertion = jwt.sign(payload, privateKey, { 
  algorithm: 'RS256' 
});

// Exchange JWT for access token
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: assertion
  })
});

  

Client Credentials Flow

System-to-System Authentication

Best for:
  •  System-to-system authentication
  •  Backend services accessing Salesforce resources
  •  Service accounts for automation
Security level : High (4/5)

Direct credential exchange for backend services accessing Salesforce resources

Implementation Steps:
Credential Exchange

Sign JWT with private key and required claims

Token Response

Exchange JWT assertion for access token

API Calls

Use access token for API calls

Flow endpoint

Authorization:

https://login.salesforce.com/services/oauth2/token

Client Credentials Flow Example

// Client Credentials Flow
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: clientId,
    client_secret: clientSecret
  })
});

const tokenData = await response.json();
const accessToken = tokenData.access_token;

  

PKCE Flow

Proof Key for Code Exchange

Best for:
  • Mobile applications requiring enhanced security
  • Public clients that cannot store secrets
  • Applications vulnerable to authorization code interception
Security level : High (5/5)

Enhanced security for mobile and public clients using code challenge/verifier

Important Note:
  • Now default for Mobile SDK 11.0+
  • Prevents authorization code interception attacks
Implementation Steps:
Generate Code Challenge

Create code verifier and challenge for security

Authorization Request

Include code challenge in authorization URL

3 Token Exchange

Exchange code + verifier for tokens

Flow endpoint

Authorization:

https://mycompany.my.salesforce.com/services/auth/idp/metadata

Token:

https://login.salesforce.com/services/oauth2/token

PKCE Flow Example

// PKCE Flow Implementation
const crypto = require('crypto');

// Generate code verifier and challenge
const codeVerifier = crypto.randomBytes(32).toString('base64url');
const codeChallenge = crypto
  .createHash('sha256')
  .update(codeVerifier)
  .digest('base64url');

// Authorization URL with PKCE
const authUrl = `https://login.salesforce.com/services/oauth2/authorize?` +
  `response_type=code&` +
  `client_id=${clientId}&` +
  `redirect_uri=${encodeURIComponent(redirectUri)}&` +
  `code_challenge=${codeChallenge}&` +
  `code_challenge_method=S256`;

// Token exchange with code verifier
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: clientId,
    code_verifier: codeVerifier,
    redirect_uri: redirectUri
  })
});

  

Device Authorization Flow

Device Code Grant

Best for:
  • IoT devices with limited input capabilities
  • Smart TVs and streaming devices
  • Hardware devices without browsers
Security level : High (4/5)

Enables authentication for devices with limited input capabilities

Important Note:
  • Device code valid for 10 minutes
  • Requires separate user authorization on different device
Implementation Steps:
Device Code Request

Device requests device code and user code

User Authorization

User enters code on separate device/browser

Token Polling

Device polls for token until authorizede

Flow endpoint

Token:

https://login.salesforce.com/services/oauth2/token

Device Authorization Flow Example

// Device Authorization Flow
// Step 1: Request device code
const deviceResponse = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    response_type: 'device_code',
    client_id: clientId,
    scope: 'api'
  })
});

const deviceData = await deviceResponse.json();
console.log(`Enter code: ${deviceData.user_code} at ${deviceData.verification_uri}`);

// Step 2: Poll for token
const pollForToken = async () => {
  const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
      device_code: deviceData.device_code,
      client_id: clientId
    })
  });
  
  if (response.ok) {
    return await response.json();
  }
  // Continue polling
};

  

REST API Integration

Synchronous API

Best for:
  • Real-time data synchronization between systems
  • Mobile applications requiring live data
  • Web applications with immediate data needs 
Complexity level : low(2/5)

Real-time data exchange using Salesforce REST APIs for CRUD operations and queries

pros

Real-time data access

Simple HTTP-based protocol

Excellent for CRUD operations

Native Salesforce support

cons

API rate limits apply

Synchronous processing only

Not suitable for large data volumes

Requirements
  •  Valid OAuth access token

  •  Proper API permissions

  • Understanding of Salesforce data model

REST API Integration Example

// Step 1: Authorization URL
const authUrl = `https://login.salesforce.com/services/oauth2/authorize?` +
  `response_type=code&` +
  `client_id=${clientId}&` +
  `redirect_uri=${encodeURIComponent(redirectUri)}&` +
  `scope=full%20refresh_token`;

// Step 2: Token Exchange
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: clientId,
    client_secret: clientSecret,
    redirect_uri: redirectUri
  })
});
  

Bulk API Integration

Asynchronous Bulk Processing

Best for:
  • Data migrations from legacy systems
  • ETL processes for data warehousing
  • Batch processing of large record sets
Complexity level : High(4/5)

High-volume data processing using Salesforce Bulk API for large-scale data operations

pros

Handles millions of records

Optimized for large data volumes

Parallel processing capabilities

Lower API consumption per record

cons

Asynchronous processing complexity

Requires job monitoring

Not suitable for real-time needs

Requirements
  • Bulk API permissions
  •  CSV or JSON data format
  •  Job monitoring implementation
Bulk API Integration Example

// Step 1: Create Bulk Job
const createJob = await fetch('https://yourInstance.salesforce.com/services/data/v58.0/jobs/ingest', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`
  },
  body: JSON.stringify({
    object: 'Account',
    operation: 'insert',
    lineEnding: 'LF'
  })
});

// Step 2: Upload CSV Data
const upload = await fetch(`https://yourInstance.salesforce.com/services/data/v58.0/jobs/ingest/${jobId}/batches`, {
  method: 'PUT',
  headers: {
    'Content-Type': 'text/csv',
    'Authorization': `Bearer ${accessToken}`
  },
  body: csvData
});

// Step 3: Close the Job
await fetch(`https://yourInstance.salesforce.com/services/data/v58.0/jobs/ingest/${jobId}`, {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`
  },
  body: JSON.stringify({ state: 'UploadComplete' })
});
  

Platform Events

Event-Driven Architecture

Best for:
  •  Real-time notifications to external systems
  •  Event-driven microservices architecture
  •  Audit trail and compliance logging
Complexity level : Medium(3/5)

Real-time event streaming using Salesforce Platform Events for decoupled integrations

pros

Real-time event delivery

Decoupled architecture

High reliability with replay

Scalable event processing

cons

Requires event design expertise

Additional licensing may be required

Complex error handling

Requirements
  • Platform Event license (if high volume)
  • Custom platform event definitions
  • Streaming API client implementation
Flow endpoint

Token:

https://login.salesforce.co/services/oauth2/token

JWT Bearer Token Flow Example

// JWT Bearer Token Flow
const jwt = require('jsonwebtoken');
const fs = require('fs');

// Create JWT assertion
const privateKey = fs.readFileSync('private.key');
const payload = {
  iss: clientId,
  sub: username,
  aud: 'https://login.salesforce.com',
  exp: Math.floor(Date.now() / 1000) + 300
};

const assertion = jwt.sign(payload, privateKey, { 
  algorithm: 'RS256' 
});

// Exchange JWT for access token
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: assertion
  })
});

  

Change Data Capture

Data Change Streaming

Best for:
  •  Data warehouse synchronization
  •  External system data replication
  •  Audit and compliance tracking
Complexity level : Medium(3/5)

Near real-time capture of data changes using Salesforce Change Data Capture events

pros

Automatic change detection

Near real-time delivery

Minimal impact on DML operations

Standard and custom objectsExcellent for CRUD operations

cons

Limited to supported objects

Requires streaming client

Event ordering not guaranteed

Requirements
  •  Change Data Capture enabled for objects
  • Streaming API client
  • Proper event handling logic
Flow endpoint

Token:

https://login.salesforce.com/services/oauth2/token

JWT Bearer Token Flow Example

// JWT Bearer Token Flow
const jwt = require('jsonwebtoken');
const fs = require('fs');

// Create JWT assertion
const privateKey = fs.readFileSync('private.key');
const payload = {
  iss: clientId,
  sub: username,
  aud: 'https://login.salesforce.com',
  exp: Math.floor(Date.now() / 1000) + 300
};

const assertion = jwt.sign(payload, privateKey, { 
  algorithm: 'RS256' 
});

// Exchange JWT for access token
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: new URLSearchParams({
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: assertion
  })
});

  

OAuth Flow Comparison

Choose the right OAuth flow based on your application requirements

Flow Comparison Table

Flow Type Security Level Use Case Client Secret Tokens
Web Server Flow
High
Web applications with secure backend
Required
Access + Refresh
User-Agent Flow
Medium
Mobile apps, SPAs
Not Required
Access Token
JWT Bearer Token Flow
High
Server-to-server, no user interaction
Certificate
Access Token
PKCE Flow
Very High
Mobile apps (SDK 11.0+)
Not Required
Access + Refresh
Device Authorization Flow
High
IoT devices, hardware authentication
Optional
Access + Refresh

Decision Tree

Can your application securely store secrets?

Yes: Web Server Flow or JWT Bearer Token

No: User-Agent Flow or PKCE Flow

Do you need user interaction?

Yes: Web Server Flow or User-Agent Flow

No: JWT Bearer Token or Client Credentials

Is this for a mobile application?

Yes: PKCE Flow (recommended) or User-Agent Flow

No: Web Server Flow or JWT Bearer Token

Security Considerations

Token Lifetimes

  • Access tokens: Configurable (default 2 hours)
  • Refresh tokens: Long-lived, revocable
  • Authorization codes: 10 minutes

Best Practices

  • Always use HTTPS for all OAuth flows
  • Store tokens securely (encrypted)
  • Implement proper token refresh logic
  • Use least-privilege scopes
  • Regular token rotation for long-lived integrations