Salesforce OAuth Just Got an Upgrade: External Client App (Full Implementation Guide)

If you’ve worked with Salesforce integrations before, chances are you’ve used Connected Apps

Well… not anymore. 

Salesforce has officially shifted towards External Client Apps, and if you’re building modern integrations in 2025, this is the way forward. 

I recently implemented a Client Credentials OAuth flow using External Client Apps — and in this blog, I’ll walk you through the entire journey: 

  • Setting up the External Client App 
  • Configuring OAuth (the right way) 
  • Generating access tokens 
  • Hitting Salesforce APIs 
  • Testing everything using Postman 

 

Let’s get into it 👇 

Step 1: Creating the External Client App 

Head over to: 

👉 Setup → App Manager → New External Client App 

This is your new “Connected App”. 

OAuth Configuration (This is where things matter) 

Once you enable OAuth, you’ll need to define scopes. 

Here’s what I used (and why): 

  • api → To access Salesforce REST APIs 
  • refresh_token → Future-proofing (even though not used in this flow) 
  • openid → 🔥 Important — gives access to a unique user identifier 

That openid scope is often skipped, but it’s becoming increasingly important in identity-aware integrations. 

Callback URL 

Even though we’re using Client Credentials Flow, Salesforce still asks for this. 

I just used: 

https://localhost/callback 

 

Step 2: OAuth Policies & Flow Enablement 

This is where External Client Apps feel more structured (and slightly stricter). 

Enable Client Credentials Flow 

In the OAuth Flow settings, make sure you: 

✔ Enable Client Credentials Flow 

Then define: 

👉 Run As User 

Example: 

test.user@abc.com 

This is super important. 

💡 Your entire API execution will run under this user’s permissions. 

So if something fails later… this is the first place to check. 

Security Settings 

Here’s what I configured: 

  • ✅ Enable Refresh Token Rotation 
  • ✅ Relax IP restrictions 
  • ✅ Refresh token expiry → 365 days 

Even though refresh tokens aren’t used in this flow, enabling rotation is a good security practice

 

Step 3: Get Client ID & Secret 

Once saved, Salesforce gives you: 

  • Client ID 
  • Client Secret 

Keep these safe — this is basically your app’s identity. 

 

Step 4: Fetching the Access Token 

Now the fun part. 

We hit Salesforce’s token endpoint: 

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

(Use test.salesforce.com for sandbox) or add your Org Domain 

🧾 Request Details 

Method: POST 
Content-Type: application/x-www-form-urlencoded 

Body: 

grant_type=client_credentials 
client_id=YOUR_CLIENT_ID 
client_secret=YOUR_CLIENT_SECRET 

✅ Response 

You’ll get something like: 


  “access_token”: “00Dxx0000001gPFEAY!…”, 
  “instance_url”: “https://yourInstance.salesforce.com”, 
  “token_type”: “Bearer” 

And just like that — you’re authenticated 🎯 

 

Step 5: Setting It Up in Postman 

This is how I tested everything end-to-end. 

🔹 Token Request 

Create a POST request with: 

  • URL → /services/oauth2/token 
  • Body → x-www-form-urlencoded 

Then add this script in the Tests tab

let res = pm.response.json(); 
pm.environment.set(“access_token”, res.access_token); 
pm.environment.set(“instance_url”, res.instance_url); 

Now your token is stored automatically 🙌 

 

Step 6: Creating a Record via API 

Let’s create an Account. 

Endpoint 

{{instance_url}}/services/data/v60.0/sobjects/Account/ 

Headers 

Authorization: Bearer {{access_token}} 
Content-Type: application/json 

Body 


  “Name”: “Test Account from External Client App”, 
  “Industry”: “Technology” 

✅ Response 


  “id”: “001xx000003DGbYAAW”, 
  “success”: true, 
  “errors”: [] 

Boom. Record created 🚀 

 

⚠️ Things That Might Trip You Up 

Let me save you a few hours of debugging: 

  1. “Why am I getting insufficient access?”

👉 Check the Run As User 

  • Does the user have object permissions? 
  • Field-level access? 
  1. “Where is my refresh token?”

You won’t get one. 

👉 Client Credentials Flow does not return refresh tokens,Just request a new access token when needed. 

  1. “invalid_clienterror?”

Usually means: 

  • Wrong client ID/secret 
  • Flow not enabled 

 

🧠 Final Flow (Simplified) 

External Client App 
      ↓ 
Client ID + Secret 
      ↓ 
Token Request 
      ↓ 
Access Token 
      ↓ 
Salesforce API 
      ↓ 
Data Created 

 

🎯 Final Thoughts 

External Client Apps feel like Salesforce finally catching up with modern OAuth practices. Cleaner. More secure. More structured. And honestly — once you set it up once, it’s pretty smooth. 

 

In this article:
Share on social media: