Securing Salesforce Integrations with Heroku AppLink
- Last Updated: September 10, 2025
Salesforce customers often leverage third-party or custom services to extend their orgs, and they do so with two common options: Connected Apps and External Services. Connected Apps let third-party vendors or custom code call Salesforce APIs using long-lived OAuth tokens, while External Services call vendor APIs through declarative configurations with vendor-managed hosting, scaling, and endpoint security. While both approaches deliver functionality, the dynamic security threat landscape challenges us to continuously improve the risk and governance of our applications.
Heroku AppLink improves your security model and provides a managed bridge between Salesforce and Heroku, so developers or vendors can deploy services in any language and expose them as native Salesforce actions. Heroku AppLink automatically handles authentication, service discovery, and request validation while its service mesh and short-lived credentials mean that your integrations no longer depend on stored credentials or exposed endpoints. Development teams can reuse existing code and libraries instead of rewriting in Apex, admins get centralized visibility into connections and authorizations, and security teams gain tighter trust boundaries across both Connected App and External Service scenarios.
In this post, we’ll explain how AppLink enforces trust at each step across both directions of integration traffic and give you concrete actions you can take when building.
Securing Salesforce outbound API calls with AppLink
Salesforce orgs often call out to external logic like AI models, payment gateways, or industry-specific APIs that live on public clouds or are operated by a third-party vendor. Traditionally, the vendors expose a public endpoint and trust any client presenting a bearer token. This delivers functionality but creates risk. If a token is stolen or the endpoint is misconfigured, attackers can replay calls and pull data directly from Salesforce.
Heroku AppLink solves this by putting a service mesh in front of the integration service when it is deployed. Instead of a public endpoint, only Salesforce orgs that you explicitly connect can reach the app. The mesh validates each request before handing safe context to the SDK. This ensures that inbound traffic is authenticated at the org level, not just by a token.
For customers, this means you can ask vendors to move their integration service onto Heroku with AppLink and gain the assurance that only your org can invoke it. For vendors, it means they can take the same Node.js or Python service running in AWS or Azure, deploy it to Heroku, and instantly benefit from Salesforce-native request validation.
Setting up a Salesforce External Service with AppLink on Heroku
Provision the AppLink add-on
heroku addons:create heroku-applink -a example-app
Add the service mesh buildpack
heroku buildpacks:add --index=1 heroku/heroku-applink-service-mesh -a example-app
Connect the Salesforce org
Publish an API spec as an External Service
Assign the generated permission set to users who will invoke the External Service action.
Inbound API calls to Salesforce: scoped, on-demand credentials
External services often need to call back into Salesforce to update records, write support case notes, or sync customer data. Salesforce enables this by storing long-lived OAuth refresh tokens. The risk of those tokens being compromised gives malicious actors broad, long-term access to bypass MFA, which is often a weakness targeted in token replay attacks.
Heroku AppLink employs short-lived credentials obtained at runtime for outbound calls for services deployed on Heroku. For user and user-plus modes, vendors do not need to cache refresh tokens, and in authorized-user mode, AppLink stores a customer-controlled authorization for a named integration user, which contains the credential material needed to obtain short-lived credentials. These authorizations are scoped and managed within the AppLink add-on, not in a multi-tenant vendor system. Each call is scoped by the mode you select:
- User mode runs with the permissions of the Salesforce user invoking the service.
- User-plus mode adds a temporary session permission set defined in your API spec.
- Authorized-user mode runs as a designated integration identity that you authorize.
Salesforce customers can request that vendors utilize AppLink to secure inbound calls and prevent the storing of tokens that can be replayed against a Salesforce org. Using AppLink also benefits the vendors to continue to run the same integration logic but with stronger controls that satisfy enterprise security requirements.
Using AppLink authorizations for calls to Salesforce
Publish with user-plus mode
heroku salesforce:publish api-spec.yaml \
--client-name MyAppAPI \
--authorizationPermissionSetName MyAppUserPlusSet \
-a example-app
Add an authorization for authorized-user mode
heroku salesforce:authorizations:add auth-user \
--addon applink-regular-78506 \
-a example-app
And in code:
const auth = getAuthorization('org_name');
To understand the critical importance of this design, it’s helpful to examine the common attack pattern that AppLink prevents. This pattern has enabled recent data thefts by exploiting long-lived tokens.
When long-lived tokens turn into attack vectors
Consider a scenario where an integration provider stores OAuth tokens for many Salesforce orgs. These tokens are long-lived and grant broad access to Salesforce APIs and can lead to the following attack scenarios:
- Token replay for direct API access: The attacker can present the stolen token to Salesforce and gain the same access as the connected app. This bypasses MFA and session controls since OAuth bearer tokens are accepted until revoked.
- SOQL reconnaissance: With valid tokens, the attacker can issue queries against objects like User, Case, Account, and Opportunity to inventory sensitive data. They can count records, filter by fields, and identify where credentials or secrets might be stored in free-text fields.
- Bulk API data export: Once valuable objects are identified, the attacker can launch Bulk API jobs to extract large volumes of records quickly. This method is efficient and can drain high-value datasets with a handful of requests.
- Covering tracks: After completing Bulk API jobs, the attacker can attempt to delete the jobs to hide evidence, making detection harder in standard monitoring flows.
Attacks that leverage long-lived OAuth tokens stored by third-party systems do not exploit Salesforce itself. They exploit the reuse of bearer tokens issued legitimately but stored outside the customer’s control.
AppLink reduces the opportunities for attackers to replay OAuth tokens dramatically because each credential is short-lived and bound to a specific org, and the service mesh enforces that only Salesforce orgs you have explicitly connected can send requests to your service on Heroku. In user and user-plus modes, tokens are not long-lived refresh tokens sitting in a vendor system. The AppLink SDK obtains short-lived, scoped credentials at runtime, tied to the mesh context and the user mode you define. Your code does not handle bearer tokens. In authorized-user mode, AppLink stores a customer-controlled authorization for a named integration user, which is then used to obtain short-lived credentials only when needed. These authorizations live with your AppLink add-on for your app, not in a multi-tenant vendor cache.
How the AppLink service mesh enforces inbound validation
Every call from Salesforce carries an x-client-context header with base64-encoded JSON that describes the org and user. The mesh allows traffic only from connected orgs before the request reaches your code. The SDK decodes this header so your app sees safe context, not raw credentials:
javascript
const ctxHeader = req.headers["x-client-context"];
const ctxJson = Buffer.from(String(ctxHeader), "base64").toString("utf8");
const ctx = JSON.parse(ctxJson);
The SDK decodes x-client-context automatically. Read it manually only for troubleshooting.
This context is what your app uses to decide business logic. You never see or manage bearer credentials directly.
How the AppLink service mesh enforces scoped outbound calls
When your app needs to call Salesforce, AppLink obtains a short-lived credential at runtime based on the user mode. In user or user-plus mode, the credential reflects the invoking user’s rights and any session permission set you defined at publish time. In authorized-user mode, you first add an authorization, then reference it in code so the SDK can obtain a short-lived credential when needed:
bash
heroku salesforce:authorizations:add auth-user \
--addon applink-regular-78506 \
-a example-app
javascript
const auth = getAuthorization("org_name"); // default add-on
// or specify a particular attached add-on by name or UUID
const auth2 = getAuthorization("org_name", "applink-regular-78506");
The SDK uses that authorization to obtain a short-lived token only when needed, and it expires quickly.
Built-in protection against credential replay
The mesh ties every inbound request to a connected org and every outbound call to a fresh, short-lived credential. Captured credentials have very limited replay value since they expire quickly and are bound to a specific org and mesh context
This design is what closes the gap exploited in token replay attacks. The mesh validates the caller, the SDK scopes the action, and the credentials themselves expire fast enough to have no value if stolen.
Why this matters to developers and security teams
Salesforce customers extend their orgs in two main ways. Connected Apps let vendors call Salesforce APIs, but often require storing long-lived OAuth tokens. External Services let Salesforce call out to vendor APIs, but put endpoint security and token handling on the vendor. Both approaches work but introduce risk.
AppLink strengthens this model by combining the usability of External Services with managed security and by removing the token exposure often seen with Connected Apps:
- No long-lived credential storage. Credentials are minted per request by the mesh, not cached by vendors.
- Validated inbound traffic. Only explicitly connected Salesforce orgs can reach the Heroku app.
- Scoped outbound calls. User, user-plus, and authorized-user modes enforce least privilege.
- Governed publication. APIs are registered in the Salesforce API Catalog, giving admins and security teams visibility.
- Reduced blast radius. Credentials are tied to a single org and cannot be replayed across customers.
This means Salesforce customers can keep using External Services to connect to third-party APIs and can still rely on Connected Apps where needed, but by adopting AppLink or requiring vendors to use it, both patterns gain stronger controls, better governance, and a lower risk profile.
Strengthening Salesforce integration security with AppLink
Long-lived tokens create risk when stored and reused. AppLink eliminates that risk by obtaining short-lived, scoped credentials at runtime through the service mesh. In authorized-user mode, AppLink maintains a customer-controlled authorization for a designated integration user, scoped to your Heroku app and used only to obtain short-lived credentials when needed.
Whether you are building, buying, or managing integrations, AppLink provides a consistent framework for securing and governing them.
- Customers building their own integrations can adopt AppLink directly to secure inbound and outbound traffic.
- Customers who rely on ISVs or partners can raise the bar by requiring those vendors to use AppLink as their integration pattern.
- Developers benefit from cleaner integration workflows.
- Admins gain visibility and control over what is connected.
- Security teams and CISOs get stronger assurance that integrations cannot be replayed or abused.
Adopting AppLink and asking partners to do the same improves security and trust for every Salesforce org.
- Originally Published:
- AppLinksalesforcesecurity