Client Credentials
Module 3 of 6 in the chapter OAuth: The Base Pattern, chapter 8 of Securing Salesforce: Identity and Access. Each module stands on its own.
The question this module answers: What does a program present at the entrance today, and what comes back?
The same shape, the current form
Section titled “The same shape, the current form”In module 2, a person’s password went to the entrance. Now substitute it. Take out the person’s username and password, and put in the program’s own credentials: the client ID and the secret of its app. That’s the client credentials flow.
Salesforce describes it as “a more secure alternative to the OAuth 2.0 username-password flow” (S1). Same two steps, same entrance, same stall. Only one card in the picture has changed.
Integration Architect teaches this flow from the integration’s side: setting it up step by step in its chapter 4, and the integration user in its chapter 13. Here we read the protocol: what goes in, what comes out, and what each part means.
The request
Section titled “The request”The client posts to the token endpoint on your My Domain (S1):
POST /services/oauth2/token HTTP/1.1Host: MyDomainName.my.salesforce.com
grant_type=client_credentials&client_id=*******************&client_secret=*******************grant_type=client_credentialsnames the flow.client_idis the app’s consumer key, andclient_secretits consumer secret, both from the app’s settings in External Client App Manager (S1).
Three details trip people up.
My Domain only. “For this flow, requests to https://login.salesforce.com (opens in a new tab) and https://test.salesforce.com (opens in a new tab) aren’t supported. Use your My Domain URL instead” (S1). Old scripts that send everything to login.salesforce.com fail here.
Body or header. The ID and secret can go in the body, as above, or “for added security”, in a Basic authorization header, the two joined with a colon and Base64-encoded (S1). Never in the address: “Don’t use GET parameters in the URL query string to pass sensitive information” (S1).
No scopes in the request. “Because Salesforce doesn’t support scopes on the token endpoint, you can’t include scopes in the request. Instead, assign scopes to your external client app” (S1). The app decides what the wristband allows, not the caller. Module 4 is about that.
The answer
Section titled “The answer”If the entrance accepts the credentials, it answers in JSON (S1):
{ "access_token": "*******************", "instance_url": "https://yourInstance.salesforce.com", "id": "https://login.salesforce.com/id/00Dx00000000001/005x00000000001", "token_type": "Bearer", "scope": "id api", "issued_at": "1762272000000", "signature": "*******************"}Read it field by field:
| Field | What it is |
|---|---|
access_token | The wristband. Shown on every call to the stall |
instance_url | Where the stall is: the address to send API calls to |
id | An identity URL naming the org and the integration user: …/id/orgID/userID |
token_type | Bearer: whoever holds it can use it, so treat it like the access it is |
scope | What kinds of access the wristband carries, from the app (module 4) |
issued_at | When it was issued, in milliseconds |
signature | A signature made with the client secret, so the client can check the id URL hasn’t changed |
What’s not in the answer matters too. There’s no refresh token: “This flow doesn’t support refresh tokens” (S1). When the wristband runs out, the program goes back to the entrance with its ID and secret and gets a new one. It doesn’t need a re-entry pass, because it never needed a person.
Who it runs as
Section titled “Who it runs as”A token has to be someone’s. In the username-password flow it was the person whose password was sent. In client credentials there’s no person, so you choose one: the flow “does require you to specify an integration user to run the integration” (S1). In the app’s policies, you enable the flow and enter “the execution user’s username” (S8).
Everything the program does is done as that user. Every record it creates or changes shows that user. And it reaches what that user may see, and nothing more.
So who should that user be? I always ask the room: if the integration user can see everything, what can the program see? Everything. And if it’s a trading app, would you want one customer’s program seeing another customer’s money? You would not. Salesforce recommends “one Salesforce user for every integration”, with the Salesforce Integration license and the Minimum Access - API Only Integrations profile (S11). Chapter 5, module 4 asked whether you should use an integration user at all; Integration Architect chapter 13, module 4 is the whole argument for one integration, one identity.
The secret is the entrance
Section titled “The secret is the entrance”Here’s the warning Salesforce puts at the top of this flow’s page: “With this flow enabled, any person or app that has access to your external client app’s consumer key and consumer secret can get an access token” (S1).
Read that again with the food festival in mind. There’s no person to check, no MFA, no login screen. The ID and secret are the proof. Whoever has them can walk to the entrance and get a wristband for the integration user.
So the secret is treated like a password, because it is one: kept in a secret store, never in code or a chat, changed on a schedule, and changed at once if it leaks (S1, S8). Integration Architect chapter 13, module 8 covers where secrets live.
Setting it up, in a line
Section titled “Setting it up, in a line”In External Client App Manager: edit the app’s settings, enable OAuth, choose its scopes, and select Enable Client Credentials Flow; then edit its policies, enable the flow there too, and enter the execution user (S8, S9). The practice at the end of this chapter walks it, with a narrow scope on purpose.
What’s next
Section titled “What’s next”Module 4: what the wristband lets you do, the scopes.
What an architect decides here
Section titled “What an architect decides here”- Which integrations use client credentials: a program with no person there, acting as its own user.
- The execution user for each one, with only the access it needs.
- Where the client secret lives, who can read it, and how it’s changed.
- That every token request goes to your My Domain, not login.salesforce.com.
Explore
Section titled “Explore”- OAuth 2.0 Client Credentials Flow for Server-to-Server Integration (opens in a new tab) (Salesforce Help, Winter ‘27; checked 2026-11-07)
- Configure a Client Credentials Flow (opens in a new tab) (Salesforce Help, Winter ‘27; checked 2026-11-07)
- Give Integration Users API Only Access (opens in a new tab) (Salesforce Help, Winter ‘27; checked 2026-11-07)
