For every API I'm consuming from Salesforce so far, I'm using the Client Credentials Grant for everything that's just between servers (= no user involved). It seems that Salesforce itself does not support the Client Credentials Grant at all. If so, why? And is my assumption even correct? What would be an alternative - and why?
3 Answers
All transactions in Salesforce are user-based. User access determines field level and record level access, page layouts, and so on. There's absolutely no way to perform an action as an anonymous "non-user." Even automated processes use an "Automated User" user for logging actions against. This is related to the auditing capabilities of Salesforce. The typical alternative is to log in as an admin or integration user.
-
You do have a point there. Still I'm wondering why Salesforce is having an "Automated User" while there's no way for us to do so - without wasting a license for a dedicated user that is. I mean - it does make sense since Salesforce is so user centric but then again - why having something that you won't give to your users? On the other hand - that wouldn't be the first feature that is only available to Salesforce and not to its users. Thanks for the clarification.– SemmelCommented Mar 11, 2019 at 9:46
-
@sfdcfox I don't see anything that identifies the running integration user for the M2M JWT Bearer Flow based on a read-through the documentation. It appears the "sub" property that would identify a particular SF user is only needed in Exp Cloud scenarios. Am I missing something? Commented Jul 5, 2022 at 18:18
-
(Unless the "prn" property is required in absence of the "sub" property; confusing language about the "sub" property only being required in Exp Cloud scenarios) Commented Jul 5, 2022 at 18:57
-
@Bow-chicawow-ers I'm pretty sure that prn is required. Again, every transaction in Salesforce is logged against some kind of user, even if it's a hidden or system user. I don't know a lot about JWT, but presumably there must be a way for it to identify the running user (or maybe it really just runs as automated user without a sub property?)– sfdcfox ♦Commented Jul 5, 2022 at 19:59
It's correct that you cannot perform a Client Credentials grant, but headless authentication, scoped to a user, is pretty easy. You can accomplish this with the OAuth 2.0 JWT Bearer Token Flow
Simplified steps...
- Create a Connected App
- Generate an X509 Cert and upload the cert to the Connected App
- Set the connected app policy to Admin approved users are pre-authorized
- Give one or more of your users access to the app via Permission Sets or Profiles.
- Make sure your external application has access to the X509 private key. Take care to store this securely with your application.
- Generate a JWT using the user you'd like to authenticate with. You'll set their username to the
sub
property. You'll sign it with the X509 private key. - Post it to the token endpoint with
grant_type
equal tourn:ietf:params:oauth:grant-type:jwt-bearer
This will return you an access token. Find a library in your preferred language to help with the construction and signing of your JWT. More details in the link above.
-
2
-
2This is one of the things that really baffles me - we seem to have tons of ways to connect to Salesforce but if I want to consume another API from Salesforce I find myself writing code from scratch.– SemmelCommented May 2, 2019 at 19:46
-
1Regarding "Find a library in your preferred language to help with the construction and signing of your JWT." -> jwt.io lists tons of libraries per tech stack. Commented Sep 20, 2019 at 8:06
The JWT Bearer Token Flow is still a very valid alternative for server-to-server communication, but since the Winter '23 release the Client Credential Flow is now also supported by Salesforce.
The Client Credential Flow is safer than the Username-Password flow because it doesn't transmit actual user credentials, and is simpler than the JWT Bearer Token Flow because it doesn't need key management.
The call would be a simple POST to the token
endpoint, providing the client id and secret and client_credentials
as grant type in the body:
POST /services/oauth2/token HTTP/1.1
Host: MyDomainName.my.salesforce.com
grant_type=client_credentials&
client_id=*******************&
client_secret=*******************
Another option would be to Base64 encode the client id and secret in a Basic Authentication header:
POST /services/oauth2/token HTTP/1.1
Host: MyDomainName.my.salesforce.com
Header: Authorization: Basic
TXlDbGllbnRJRDpNeUNsaWVudFNlY3JldA==
grant_type=client_credentials
Salesforce returns an access token based on the executing user and the scopes that you configure in the Connected App
The documentation can be found here: OAuth 2.0 Client Credentials Flow for Server-to-Server Integration
-
Interesting! I'll have a look at this and my specific use cases. Maybe other people can share their experience with this here as well. Thanks!– SemmelCommented Nov 10, 2022 at 20:01
-
1Something to add: The user that you set as executing user needs to have an api only profile, so it cannot be just any user, so you are encouraged to use a special integration user with only the relevant permissions for this connected app.– FolkertCommented Nov 11, 2022 at 10:03