Declaratively Connect Salesforce to Salesforce with the “new” Named and External Credentials JWT Bearer Flow

Justus van den Berg
8 min readFeb 23, 2023

--

In the Salesforce Winter ‘23 release, Named Credentials have gotten an overhaul. There now is a split between Named Credentials and External Credentials which gives more flexibility and better re-usability.
When you start to work with External Credentials it might be a bit confusing at first.

A common integration pattern for connecting Salesforce to Salesforce directly, is using a named credential in combination with a service user account.
For “System to System” integrations this is usually done using the OAuth 2.0 JWT Bearer flow.

The great thing is that this OAuth flow can be set up fully declaratively: Clicks not code! It does requires a few extra steps in this “new” Named Credential world.
In this article I am refreshing my legacy guide on connecting Salesforce to Salesforce using Named Credentials by giving step by step instructions.
The header of each section indicates whether you need to perform the steps on the Hub or Spoke Org.

Remember: Always consult with your security and integration experts before implementing any type of integration.

00 :: Requirements and Terminology

Before you begin you need to have a couple of items at the ready.

  1. A Hub Org. This is the Org that will connect to one or more Spoke Orgs. Named Credentials and External Credentials are created in this org.
  2. A Spoke Org. This is the Org that the Hub Org will connect to. A Connected App for the Hub Org will be created on each Spoke Org.
  3. A Certificate. For Production (like) Orgs this should always be a CA signed certificate. For test Orgs without any production (user) data, a Self Signed Certificate will do.
  4. The My Domain Name for both the Hub Org and the Spoke Org.
  5. Spoke Org Service User, Username. This is the user (and its security and sharing settings) that will be used by the Hub Org to connect to the Spoke Org.

Note: You can use this JWT Flow to connect an Org to itself. This is useful when you have Lightning Web Components that need to call the Salesforce API through Apex in a certain user context.

01 :: Hub Org :: Create a Self Signed Certificate

This Org will connect to a Spoke. For this we need a certificate. In this example we will use a self signed certificate.

  1. In Setup go to Security >> Certificate and Key Management
  2. Click the “Create a new self signed certificate” button
  3. For the “Label” put “Hub Org”, “Unique name” “Hub_Org”, “Key Size” does not matter, “Exportable Private Key” is not required.
  4. Click “Download certificate” and store the .crt file somewhere in your documents.
Details of the newly created certificate

02 :: Hub Org :: Create a Permission Set

In order to use any External Credential, Salesforce requires a Permission Set. They cannot be added to a Profile.

  1. In Setup go to Users >> Permission Sets and Click the “New” button
  2. In the “Label” put “Spoke Org External Credential
  3. The “API Name” should automatically populate
  4. The “License Type” dropdown can be kept to “None
  5. Press “Save”
  6. Assign yourself to this permission set, forgetting that might cause head scratching later.
  7. This is all for now, no need to assign any permissions

03 :: Spoke Org :: Setup the Connected App

The Hub will connect to this Spoke Org. The first step is setting up the “App” that “connects” to this spoke using a Connected App.

  1. In your spoke org go to Setup >> Apps >> App Manager
  2. Click New “Connected App”
  3. For “Name” put “Hub Org”, “Api Name” “Hub_Org” and your personal email in “Contact Email”
  4. Check “Enable OAuth Settings”, additional settings will appear
  5. In the “Callback URL” put your hub org’s My Domain Url and the callback endpoint
    i.e. “https://[HUB_ORG].my.salesforce.com/services/oauth2/callback
  6. Check “Use digital signatures” and use the “Choose File” button to upload the Certificate you downloaded from the Hub Org in step 1.4
  7. In “Selected Scopes” select “Manage user data via API” and “Perform requests at any time”. You can exchange the first option with what ever you require later if you wish.
    The second option is required to deal with the OAuth refresh tokens and keep your user logged in. You can play around with the settings if you want, but the “api” and the “refresh_token” scopes are a safe bet when testing.
  8. Press “Save” you’ll get a warning message. Just press “Continue”. It might take 10 minutes for your app to properly work. Usually it’s quicker, but keep this in mind when testing.
    You will be redirected to your Connected App.

04 :: Spoke Org :: Setup the Connected App Policies

  1. In your newly created Connected App click the “Manage” button
  2. In the policy screen click the “Edit Policy” button
  3. Under the section “OAuth Policies”, in the “Permitted Users” Dropdown select “Admin approved users are pre-authorised
  4. Press “Save”
  5. In the policy screen, scroll down, in the “Profiles” section click “Manage profiles”, check the System Administrator profile
  6. Go back to your Connected App, this has to go through Setup >> Apps >> App Manager, in the list of apps select “View” from the options arrow on the right side next the Hub Org App
  7. Click the button “Manage Consumer Details”, you might need to go through Multi Factor Authentication to see these details, this is expected.
  8. Copy the “Consumer Key”, you will NOT need the “Consumer Secret”. Store this somewhere in a note, we’ll need this in a bit.
  9. Close the window. Always keep consumer data safe
  10. Note: Giving your administrator profile access and not specifying IP Ranges is for testing purposes only. Always discuss the security settings with your company’s security team and follow the principle of least access.

05 :: Hub Org :: Create External Credential

We are going to set up the Hub to connect to a spoke using a Named Credential. The credential will have the name of the spoke it connects to.

  1. In the Hub Org go to Setup >> Security >> Named Credentials
  2. Click on the tab “External Credentials” and press the “New” button
  3. A form will popup. For the “Label” put “Spoke Org” and or the “Name” put “Spoke_Org
  4. In “Authentication Protocol” select “OAuth 2.0” with the “Authentication Flow Type” set to “JWT Bearer Flow”, “Scope” can be kept blank.
  5. The “Identity Provider Url” contains the token endpoint from the spoke org. Use the spoke org’s My Domain Name and the token endpoint.
    i.e. “https://[SPOKE_ORG].my.salesforce.com/services/oauth2/token
  6. Set the “Signing Certificate” to the “Hub Org” self signed certificate you created in step 1.4. “JWT Expiration” can be left blank.
  7. Press Save

06 :: Hub Org :: Setup External Credential Permission Set

  1. In your newly created External Credential scroll down to the section “Permission Set Mappings” and click “New
  2. Select the Permission Set you created in step 02 (“Spoke Org External Credential”)
  3. “Sequence number” can be kept to the default value
  4. “Identity Type” should be set to “Named Principal
  5. Press Save

06 :: Hub Org :: Setup JWT Claims

The difference with the “Old” way of setting up your connections, is that you have more freedom in the way you set up your JWT Tokens. This results in a few exra steps required to setup your JWT Claims.

  1. In your newly created External Credential scroll down to the section “JWT Claims”, this comes after the “Permission Set Mappings” section.
  2. Click the “Edit” button. You’ll now see a number of claim sections we have to populate.
  3. In the claim with the name “iss” (Issuer) put the “Consumer Key” you copied in step 4.8.
  4. In the claim with the name “sub” (Subject) put the “Username” from the Spoke Org you connect with (Note: Based on the Connected App security settings this has to be a System administrator, but this should be aligned with a Permission Set in production (like) environments)
  5. In the claim with the name “aud” (Audience) put “https://login.salesforce.com” for production Orgs (and Developer Edition Orgs) and “https://test.salesforce.com” for Sandboxes (and Scratch Orgs)
  6. The kid (Key Id) Claim will be set to the API Name of the certificate. You can leave this as it is or delete the claim.
  7. Press Save

07 :: Hub Org :: Setup Named Credential

The last step is setting up the Named Credential.

  1. Go to setup >> Security >> Named Credentials
  2. Click the tab “Named Credentials” and click the “New” button
  3. Set the “Label” to “Spoke Org” and the “Name” to “Spoke_Org
  4. Set the URL to the Spoke Org’s My Domain Url without anything else.
    i.e. “https://[SPOKE_ORG].my.salesforce.com” This is the base URL only and is used as the base path for any API callouts.
  5. In “External Credential” select the “Spoke Org” external credential you created
  6. In “Certificate” select the “Hub Org” you created in section 5
  7. Unless you have namespaced packages you want to allow access to this named credential, you can leave the rest to their default values.
  8. Press Save

08 :: Hub Org :: Testing

Everything is setup now and should be working if you followed all the steps. Make sure you are on the Hub Org and that you have assigned the executing user the created Permission Set or you will get a permissions error.

  1. Open the “Developer Console” or any IDE of choice that can execute Apex Code Anonymously.
  2. Execute the below code block that uses the Named Credential syntax with our Named Credential’s name “callout:Spoke_Org/services/data”
    In the test I have added the data endpoint. Please note that the name is case sensitive an there should be no whitespace around it.
HttpRequest request = new HttpRequest();
request.setEndPoint('callout:Spoke_Org/services/data');
request.setMethod('GET');
HttpResponse response = new HTTP().send(request);
System.assertEquals(200, response.getStatusCode());

If there are no Assertion Errors and the code executes successfully, you are good to go.

Although used in Apex, you’ve created the actual integration with clicks, not code. Named Credentials can be used with Flows and External Services.

09 :: Final notes

Creating integrations with the JWT OAuth flow is easy and secure when implemented correctly. You have to be careful and always follow the guidelines and best practices as set out by your security team.

You should also check if this type of integration pattern is the correct pattern for your use case. Always consult with an integration expert before implementing.

Finally: I am a Salesforce employee, the above article describes my personal views and techniques only. They are in no way, shape or form official advice. It’s purely informative.
Anything from the article is not per definition the view of Salesforce as an Organization.

If you have any comments or spotted any errors please let me know.

10 :: Final final notes

When using Salesforce’s JWT Named Credentials, the token endpoint is called in the format as described in Section 2.1 of RFC-7523.

If you have other JWT token flows like a client credentials flow, the standard as described in section 2.2 is used. The only way I found this to work with this is using an Auth Provider with an custom AuthProviderPluginClass implementation. But let me know if you have other ideas.

--

--