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:
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:
- “Why am I getting insufficient access?”
👉 Check the Run As User
- Does the user have object permissions?
- Field-level access?
- “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.
- “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.





