OAuth & Authentication Flows

0/3 in this phase0/41 across the roadmap

📖 Concept

Understanding OAuth and authentication is critical for integration architecture. Salesforce supports multiple OAuth flows for different scenarios.

OAuth 2.0 Flows in Salesforce:

  1. Web Server Flow (Authorization Code) — Most common for web apps

    • User redirected to Salesforce login
    • App receives authorization code
    • App exchanges code for access token + refresh token
    • Use for: Web applications with server-side logic
  2. User-Agent Flow (Implicit) — For client-side apps

    • Access token returned directly in URL fragment
    • No refresh token
    • Use for: Single-page apps, mobile apps (legacy)
  3. JWT Bearer Token Flow — Server-to-server (no user interaction)

    • App uses a private key to sign a JWT
    • Salesforce validates and returns an access token
    • Use for: Backend integrations, CI/CD, automated processes
  4. Client Credentials Flow — Machine-to-machine

    • App uses client ID + secret to get a token
    • No user context — runs as an integration user
    • Use for: System integrations, data sync
  5. Device Flow — For devices with limited input

    • Device displays a code, user authorizes on another device
    • Use for: IoT devices, CLI tools
  6. Refresh Token Flow — Renew expired access tokens

    • Use refresh token to get a new access token
    • Avoids re-authentication

Connected Apps: To use OAuth, you must create a Connected App in Salesforce that defines:

  • Consumer Key (Client ID)
  • Consumer Secret (Client Secret)
  • Callback URL
  • OAuth Scopes (api, refresh_token, web, etc.)
  • IP restrictions and policies

Security best practices:

  • Always use HTTPS
  • Store tokens securely (never in client-side code)
  • Use the minimum required OAuth scopes
  • Implement token rotation and refresh
  • Monitor Connected App usage in Setup

💻 Code Example

codeTap to expand ⛶
1// OAuth & Authentication Patterns
2
3// 1. JWT Bearer Token Flow (Server-to-Server)
4public class JwtAuthService {
5
6 private static final String TOKEN_ENDPOINT = 'https://login.salesforce.com/services/oauth2/token';
7 private static final String CONSUMER_KEY = 'your_connected_app_consumer_key';
8
9 public static String getAccessToken() {
10 // In production, use Named Credentials instead of manual JWT
11
12 // Build JWT claims
13 Map<String, Object> claims = new Map<String, Object>{
14 'iss' => CONSUMER_KEY,
15 'sub' => 'integration@company.com',
16 'aud' => 'https://login.salesforce.com',
17 'exp' => String.valueOf(
18 Datetime.now().addMinutes(5).getTime() / 1000
19 )
20 };
21
22 // In real implementation, sign with certificate
23 // String jwt = createSignedJwt(claims, certificate);
24
25 HttpRequest req = new HttpRequest();
26 req.setEndpoint(TOKEN_ENDPOINT);
27 req.setMethod('POST');
28 req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
29 req.setBody(
30 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' +
31 '&assertion=' + EncodingUtil.urlEncode('jwt_token_here', 'UTF-8')
32 );
33
34 HttpResponse res = new Http().send(req);
35 Map<String, Object> response = (Map<String, Object>)
36 JSON.deserializeUntyped(res.getBody());
37
38 return (String) response.get('access_token');
39 }
40}
41
42// 2. Making authenticated calls to another Salesforce org
43public class CrossOrgService {
44
45 public static List<Map<String, Object>> queryExternalOrg(String soql) {
46 // Use Named Credential for auth
47 HttpRequest req = new HttpRequest();
48 req.setEndpoint('callout:Other_Salesforce_Org/services/data/v59.0/query?q=' +
49 EncodingUtil.urlEncode(soql, 'UTF-8'));
50 req.setMethod('GET');
51 req.setHeader('Accept', 'application/json');
52
53 HttpResponse res = new Http().send(req);
54
55 Map<String, Object> result = (Map<String, Object>)
56 JSON.deserializeUntyped(res.getBody());
57
58 return (List<Map<String, Object>>)
59 (List<Object>) result.get('records');
60 }
61}
62
63// 3. Custom REST API with proper authentication check
64@RestResource(urlMapping='/api/v1/secure/*')
65global with sharing class SecureRestApi {
66
67 @HttpGet
68 global static ResponseWrapper getData() {
69 // The @RestResource automatically validates OAuth tokens
70 // No manual auth check needed — Salesforce handles it
71
72 // But you should check permissions
73 if (!Schema.SObjectType.Account.isAccessible()) {
74 RestContext.response.statusCode = 403;
75 return new ResponseWrapper(false, 'Insufficient permissions');
76 }
77
78 List<Account> accounts = [
79 SELECT Id, Name, Industry FROM Account LIMIT 10
80 ];
81
82 return new ResponseWrapper(true, accounts);
83 }
84
85 global class ResponseWrapper {
86 public Boolean success;
87 public Object data;
88 public String message;
89
90 public ResponseWrapper(Boolean success, Object data) {
91 this.success = success;
92 this.data = data;
93 }
94
95 public ResponseWrapper(Boolean success, String message) {
96 this.success = success;
97 this.message = message;
98 }
99 }
100}

🏋️ Practice Exercise

OAuth & Authentication Practice:

  1. Create a Connected App in your developer org and configure OAuth scopes
  2. Use Postman to authenticate via Web Server Flow and make API calls
  3. Set up a JWT Bearer Token flow for server-to-server integration
  4. Create a Named Credential that handles OAuth token refresh automatically
  5. Build a custom REST API and test authentication with different user profiles
  6. Implement a token management service that caches and refreshes access tokens
  7. Set up IP restrictions on a Connected App and test access from different IPs
  8. Create a Canvas app that uses signed request authentication
  9. Configure OAuth policies: token lifetime, refresh token rotation, admin pre-authorization
  10. Audit Connected App usage using Setup → Connected App OAuth Usage

⚠️ Common Mistakes

  • Storing access tokens in custom settings or fields — tokens should be managed by Named Credentials, not stored in data

  • Not implementing refresh token logic — access tokens expire. Without refresh logic, integrations break

  • Using the same Connected App for all environments — create separate Connected Apps for dev/sandbox/production

  • Granting too broad OAuth scopes — 'full' scope gives complete access. Use minimum required scopes (api, refresh_token)

  • Not monitoring Connected App usage — unauthorized access can go undetected without monitoring

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for OAuth & Authentication Flows. Login to unlock this feature.