A Salesforce External Client App (ECA) is the app record that lets an outside system call Salesforce APIs over OAuth, and it is now the only kind you can create by default. Since Spring '26, new Connected Apps are off in every org, and the Winter '27 release notes say Salesforce ends support for Connected Apps in Summer '27. If you are building a new integration today, you are building it on an ECA.
For a SaaS company the harder question is not how to create one in your own org. It is how one ECA reaches hundreds of customer orgs, who controls which settings once it is installed, and what breaks for every customer if the app is set up wrong. Appnigma works with B2B SaaS teams on that customer-facing side. Our integration infrastructure handles "app registration and authorization with infra built for the systems your customers use," and our marketplace apps work builds "a Salesforce managed package or HubSpot app built around your product" when the ECA has to ship inside one.
Updated October 2026. Checked against Salesforce Help, the Metadata API Developer Guide, the ISVforce Guide and the Spring '26, Summer '26 and Winter '27 release notes. The earlier version said the global OAuth file holds only the key and secret, that staged key rotation works for any ECA, and that migrated apps always end up local. Salesforce's docs now say otherwise on all three. This update corrects them and adds a section on shipping one packaged ECA to many customer orgs.
How an External Client App splits control between you and your customer
Salesforce Help defines External Client Apps as "packageable frameworks to enable a third-party application to integrate with Salesforce using APIs and security protocols" (External Client Apps). They cover the same OAuth and SAML single sign-on jobs a Connected App did. What changed is who owns each setting. The developer owns the app's settings, and the admin of each org that installs it owns the policies. Help is blunt about it. "Subscriber org admins can't edit app settings," and their policies "are never packaged, and only affect the admin's local org."
The OAuth settings are split again into two files. The table follows the Metadata API reference, which is more precise than the Help overview's one-line summary.
| Settings layer | Metadata type | What it holds | Packaged? |
|---|---|---|---|
| Global OAuth settings | ExtlClntAppGlobalOauthSettings | Consumer key and secret, callback URL, certificate, PKCE and secret rules, and which OAuth flows are enabled | Never |
| OAuth settings | ExtlClntAppOauthSettings | Scopes and other non-secret configuration, plus an OAuth link back to the global file | Yes |
| OAuth policies | ExtlClntAppOauthConfigurablePolicies | Permitted users, refresh token policy, session rules, the client credentials execution user | No, set in each org |
The global file holds "private and sensitive OAuth consumer information that can't be packaged and must not be added to source control," per ExtlClntAppGlobalOauthSettings. That list includes the callback URL and the flow switches, not just the credentials. The packageable file "includes an OAuth link that associates the external client app with the OAuth consumer in a global OAuth settings file," per External Client Apps Association and Disassociation. Policies are "generated with default values at runtime" in each org, per the 2GP packageable components list.
External Client App distribution state: Local or Packaged
Every ECA has a distribution state, and it decides where the app can run. You pick one of two values when you create the app.
| Distribution state | Meaning |
|---|---|
| Local | Developed and used in the single org where you create it. It can't be packaged. |
| Packaged | Distributed to subscriber orgs through a managed package |
The choice has three consequences people find out late. Help says "local external client apps aren't copied to a new sandbox when you clone or refresh a sandbox. Only packaged external client apps are copied" (External Client Apps). Staged key and secret rotation works only for local apps. And after November 30, 2026, the OAuth Device flow works only on local apps, covered below. Salesforce also notes that "the only difference in configuration between a local and a packaged external client app is the Distribution State setting" (Package an External Client App), so the rest of the setup is the same.
Salesforce ECA vs Connected App
Both authorize an external system to call Salesforce APIs. Salesforce calls ECAs "the new generation of connected apps" on its feature comparison page, and the rows below come from that page.
| Dimension | Connected App | External Client App |
|---|---|---|
| Metadata model | One file, developer and admin settings combined | Separate global OAuth settings, OAuth settings and admin policies |
| Developer and admin roles | Not separated | Distinct developer and admin roles |
| 2GP packaging | Restricted | Available |
| 1GP packaging | Available | Available, only from the org where the ECA was created |
| Username-Password OAuth flow | Retiring | Not available |
| User provisioning | Available | Not available |
| Use without installation | Restricted since September 2025 | Not possible, an ECA must be installed |
| New ones can be created | Disabled by default since Spring '26 | Yes |
On the Username-Password flow, the comparison page says it "won't be made available for external client apps." For Connected Apps, Salesforce postponed its retirement to February 20, 2027 (Winter '27 release note). Uninstalled Connected Apps have been restricted since September 2025 (KA 005132365). The 1GP row is newer than most third-party comparisons. Salesforce added 1GP packaging for ECAs in Summer '26, and Help states that ECAs "can only be packaged with 1GP managed packaging in the org where they were created" (Package an External Client App with 1GP). Pages that say ECAs are 2GP-only are out of date.
Salesforce's guidance is "We recommend that you use external client apps in all situations and migrate existing local connected apps to local external client apps," on External Client Apps and Connected Apps. The same page notes that "some features are only available through connected apps," so check user provisioning and Canvas before you move an app that depends on them. For the full side by side, see Connected App vs External Client App in Salesforce.
Why the "New Connected App" button is gone
The button is missing because of a Spring '26 release note, Creation of New Connected Apps Is Disabled by Default. It says "the ability to create new connected apps is disabled by default for all Salesforce orgs," and the "Allow creation of connected apps" preference was removed. Existing Connected Apps keep working, and packaged ones still install. Knowledge article 005228017 adds that creation "via APIs (including the Metadata API) is blocked in the same way as the UI" and that "in future releases, Salesforce Support won't be able to enable the creation of new connected apps."
The end date comes from the Winter '27 release update Migrate All Connected Apps to External Client Apps. "In Summer '27, Salesforce is ending support for connected apps." The note continues that "connected apps will keep working, but Salesforce will no longer fix bugs or provide support" for the flows that use them. Salesforce has not published a day within Summer '27. The free Connected App walkthrough covers what the change means if you were following older setup guides.
How to create an External Client App, step by step
You create an ECA in App Manager, the same Setup page that used to hold the New Connected App button. The steps follow Salesforce's Create an External Client App, which needs the "Create, edit, and delete External Client Apps" permission.
- From Setup, enter App Manager in Quick Find and select App Manager.
- Click New External Client App.
- Enter a name and an API name. The API name starts with a letter, uses only letters, numbers and underscores, and can't end with an underscore or contain two in a row.
- Enter a contact email. Salesforce uses it to reach you, and "this address isn't given to Salesforce admins who install the app."
- Set the distribution state to Local for one org, or Packaged if the app will ship in a managed package.
- In the API section, select Enable OAuth.
- Enter a callback URL, the redirect URI your app returns to after login. It "must use secure HTTPS or a custom URI scheme," per Configure the External Client App OAuth Settings. For a quick Postman test, use https://oauth.pstmn.io/v1/callback.
- Select only the OAuth scopes your integration calls, then click Create.
Two tasks remain. Enable the OAuth flow you need (next section), then get the credentials. In External Client App Manager, open the app's Settings tab, expand OAuth Settings and click Consumer Key and Secret. Salesforce may ask you to "check your email for a verification code" first, per the Salesforce DX guide. Store both values in a secrets manager.
If you only need a working ECA with a managed package install link, Appnigma's free External Client App tool provisions one. You give it a name, redirect URLs and a scope preset. It returns the client ID and secret plus a managed package link, with no partner application.
Shipping one External Client App to many customer orgs
A SaaS product doesn't create an ECA in each customer's org. It creates one packaged ECA in its own org and ships it in a managed package, and every customer install points back to that one OAuth consumer. Help says the global settings file "is shared by all deployments of the external client app and must be stored on a non-ephemeral org" (Association and Disassociation). In practice that means one client ID and one secret for all customers, with tokens issued per customer org.
Each customer authorizes against their own org, using your consumer key. Salesforce documents the pattern as follows (Initiate the Authorize Endpoint for an Associated ECA).
https://<customer My Domain>/services/oauth2/authorize?response_type=code&client_id=<your consumer key>&redirect_uri=<your callback URL>Because the callback URL lives in your global settings, it is the same for every customer. Your backend has to tell customers apart by the org it receives the code from, not by the URL.
Where the source app lives matters. Salesforce recommends "second-generation managed packages along with a Dev Hub org" (Package an External Client App), and the 2GP guide says ISVs "should instead define the External Client App in their PBO (Partner Business Org) Dev Hub" (2GP packageable components). That org becomes permanent infrastructure. Help warns that "if you delete the external client app from the source org, the subscriber org's external client app breaks," which means every customer at once.
Once installed, the customer's admin controls the policies. You set starting values on the app's Package Default tab (Configure Default Settings), but Help states that after an admin edits policies, "the values persist even if the developer updates the app Settings" (Configure OAuth Policies). A new package version can't reset a customer's refresh token policy or permitted users. Scope changes go the other way. They are settings, so they reach customers only through a package upgrade.
Partner security rules also apply. The ISVforce Guide lists four controls for any app "in use by more than two customer production orgs." They are PKCE and refresh token rotation, plus a 30-day idle refresh token limit and a refresh token IP allowlist. The deadline was May 11, 2026. It adds that once PKCE is on, "partners won't be permitted to disable" it. Apps created since July 2026 get these controls on by default (Summer '26 release note). The partner OAuth security deadline guide walks through each control. If the package also needs an AppExchange listing and security review under your own namespace, that is the managed package work our marketplace apps team does, with "Salesforce security review preparation and responses."
Which OAuth flow should a Salesforce ECA use?
A Salesforce ECA supports the standard OAuth 2.0 flows except Username-Password. The table lists the flows in Salesforce's OAuth flow setup for External Client Apps and where each fits a multi-customer product.
| OAuth flow | Best for | Works in a packaged ECA |
|---|---|---|
| Web Server (authorization code) with PKCE | Each customer user or admin connecting their org from your product | Yes, the default choice |
| Client Credentials | Backend sync in one org with no user present | Yes, but each customer admin sets the execution user |
| JWT Bearer | Certificate based server to server access | Yes, needs a certificate in global settings |
| Device | CLIs and input-constrained hardware | No, after November 30, 2026 |
| Refresh Token | Keeping a connection alive without a new login | Yes, within each org's refresh token policy |
For a product that connects to many customer orgs, the Web Server flow with PKCE is the usual fit, because each customer grants access through their own login and policies. Client Credentials suits a single-org backend. Salesforce describes it as needing "an integration user to run the integration" (OAuth 2.0 Client Credentials Flow). That user is stored in policies, which the customer's admin owns, and the metadata says it "must have the API Only permission" (ExtlClntAppOauthConfigurablePolicies). The flow "doesn't support refresh tokens," and requests to login.salesforce.com "aren't supported. Use your My Domain URL instead." The integration user guide covers the license that user needs, and Salesforce External Client App OAuth goes flow by flow.
Plan for token expiry too. The Winter '27 note Refresh Token Idle TTL Is Limited to 30 Days says "refresh tokens expire if they haven't been used for 30 days." The rule "applies to external client apps and connected apps, including apps that are installed in subscriber orgs." Enforcement started in sandboxes on October 21, 2026 and in production from November 4, 2026. A customer whose sync pauses for a month will see invalid_grant and has to reconnect.
Device flow is restricted to local External Client Apps
The Winter '27 release update Restrict the OAuth 2.0 Device Flow to Local External Client Apps "is available in late Summer '26 and is enforced on November 30, 2026." From that date the flow stops working for Connected Apps and packaged ECAs. It also stops for local ECAs that "don't have a localhost callback URL." The Summer '26 version of the note adds a fourth condition many guides skip. "No other OAuth flows are enabled in the app settings." A device-flow app must be local, use a localhost callback, and do nothing else. In a packaged ECA the option is greyed out.
Create an ECA with metadata or Salesforce DX
Developers can keep an ECA in source control instead of building it in Setup. The ExternalClientApplication type uses the .eca suffix in an externalClientApps folder and is "available in API version 59.0 and later" (ExternalClientApplication). An OAuth app is deployed as that header file plus ExtlClntAppGlobalOauthSettings, ExtlClntAppOauthSettings and ExtlClntAppOauthConfigurablePolicies, and you deploy them like any other source.
sf project deploy start --manifest package.xml --target-org yourOrgThat command is the one in Salesforce's Deploy a Local External Client App. Three org-level switches govern metadata access. The ExternalClientApplication type needs the "Opt in to External Client Apps" setting. Reading or deploying the global file needs "Allow Access to OAuth Consumer Secrets via Metadata API" in the org and the "View External Client Apps Consumer Secrets in Metadata" permission for the developer. KA 005228017 adds that a CI/CD deployment user needs Manage External Client Apps. Never commit the global file. For authorizing the Salesforce CLI itself, Salesforce's DX guide walks through an ECA for the JWT login command.
Managing an External Client App after you create one
External Client App Manager in Setup is where an ECA is governed after creation, whether it is your own local app or a packaged app a customer installed. The four settings teams change most often sit on different tabs.
| What to manage | Where it lives | Why it matters |
|---|---|---|
| OAuth scopes | Settings, OAuth Settings | Every requested scope is visible to the admin who reviews the app |
| Refresh token policy | Policies, OAuth Policies | Controls how long a connection survives, within Salesforce's 30-day idle limit |
| Who can use the app | Policies, Permitted Users | Admin approved users are pre-authorized limits access to assigned profiles and permission sets |
| Active tokens | External Client Apps, OAuth Usage | Shows authorized users and lets an admin revoke one token, one user or all |
Switching Permitted Users has a sharp edge. Help warns that moving from "All Users can self-authorize" to admin approved means "anyone using the app loses access, unless a user's permission authorizes" it, and users with Use Any API Client can still reach the app (Preauthorize User App Access). Check the OAuth Usage page before a revocation, not during an incident.
Mistakes that break an External Client App after install
Most ECA support tickets trace back to a handful of setup choices. These are the ones that hit SaaS teams once customers start installing.
- Testing a packaged ECA in an org without the package. ECAs "can't be used without installation," per the comparison page. A login against an org where your package isn't installed fails, and Salesforce's restriction on uninstalled apps returns "app must be installed into org" (KA 005132365). The OAuth errors reference maps the OAUTH_APPROVAL_ERROR_GENERIC message.
- Planning key rotation on a packaged app. The staged rotation workflow in Connect REST API "doesn't apply to packaged external client apps," per Stage, Rotate, and Delete OAuth Credentials. Because the secret is shared by every customer, rotation goes through the global settings instead. The shouldRotateConsumerSecret field replaces the secret on metadata deploy (ExtlClntAppGlobalOauthSettings), so ship the new value to your backend in the same change.
- Treating the consumer secret like a config value. Salesforce warns that "any person or app that has access to your external client app's consumer key and consumer secret can get an access token" (Configure a Client Credentials Flow). Keep it in a secrets manager.
- Building the source app in a scratch org or sandbox. A packaged ECA's consumer must live on a non-ephemeral org. Choosing Local for an app that needs to reach sandboxes also fails, because local apps are not copied on refresh.
- Packaging a SAML app. "External client apps with SAML configurations can't be packaged or distributed," per ECA creation with Metadata API.
If the integration calls out from Salesforce rather than into it, the credential setup lives elsewhere. See Named Credentials and External Credentials in Salesforce.
How to migrate a Connected App to an External Client App
Moving an existing Connected App to an External Client App depends on who owns it. For a Connected App you built in your own org, Salesforce provides a migration button. Open the app in App Manager, and if it meets every eligibility rule, "you see the Migrate to External Client App button" (Connected App to External Client App Migration). Migration "preserves your consumer key and secret," and "refresh tokens remain valid." The original is kept as a read-only version, and Help says not to delete it. Six features make an app ineligible. They are user provisioning and a custom Apex handler, Canvas and dynamic client registration, Triple DES SAML encryption, and standard notification subscriptions on apps that aren't internal. Single sign-on apps can't be migrated, migration runs only in the UI, and the tool "can't detect username-password flow," which stops working afterward.
A Connected App inside your managed package is different. KA 005228017 states "it is the ISV's (the vendor's) responsibility to provide a migrated ECA version." Since Summer '26 you can "migrate connected apps that are packaged in first-generation or second-generation managed packages" to packaged ECAs, and "customer OAuth flows, tokens, and active sessions remain valid through package upgrade" (Summer '26 release note). Your customers don't reconnect, but they do need the upgrade, so the Summer '27 end of support is effectively a deadline for your next package release. Winter '27 also lets you delete a migrated packaged ECA, after which "the connected app that it was migrated from becomes active again" (Delete a Migrated, Packaged External Client App).
Frequently Asked Questions
What is a Salesforce ECA?
An External Client App, the framework that lets an outside application connect to Salesforce over OAuth or SAML. It replaced the Connected App for new integrations in Spring '26.
What is the External Client App distribution state?
Local means the app works only in the org where it was created. Packaged means it ships to customer orgs in a managed package, and only packaged apps are copied into a cloned or refreshed sandbox.
Can you still create Connected Apps in Salesforce?
Not by default. Since Spring '26, creation is blocked in the UI and through APIs except by package installation, and Salesforce ends support for Connected Apps in Summer '27.
What is the Run As user for an External Client App?
It is called the execution user. It is the API Only user that the Client Credentials flow runs as, set in the app's OAuth policies.
Can Appnigma set up our External Client App?
Yes. Our free External Client App tool provisions one with a managed package link, and our integration infrastructure handles app registration and authorization for each customer connection.
Related Articles
- Connected App vs External Client App in Salesforce
- Salesforce External Client App OAuth flows
- Salesforce Connected App security deadline for partners
- The Salesforce integration user, license and setup
- Salesforce OAuth errors and troubleshooting
- Salesforce managed package guide
Sources
- Salesforce Help, External Client Apps
- Salesforce Help, Comparison of Connected Apps and External Client Apps Features
- Salesforce Help, External Client Apps and Connected Apps
- Salesforce Help, External Client Apps Association and Disassociation
- Salesforce Help, Package an External Client App
- Salesforce Help, Package an External Client App with 1GP
- Salesforce Help, Create an External Client App
- Salesforce Help, OAuth 2.0 Client Credentials Flow
- Salesforce Help, Stage, Rotate, and Delete OAuth Credentials for a Local External Client App
- Salesforce Help, Connected App to External Client App Migration
- Salesforce Help, Knowledge Article 005228017, Connected App creation changes
- Salesforce Help, Knowledge Article 005132365, uninstalled connected apps restriction
- Spring '26 Release Notes, Creation of New Connected Apps Is Disabled by Default
- Summer '26 Release Notes, Migrate Packaged and Distributed Connected Apps to External Client Apps
- Winter '27 Release Notes, Migrate All Connected Apps to External Client Apps
- Winter '27 Release Notes, Restrict the OAuth 2.0 Device Flow to Local External Client Apps
- Winter '27 Release Notes, Refresh Token Idle TTL Is Limited to 30 Days
- Salesforce Developers, Metadata API Developer Guide, ExtlClntAppGlobalOauthSettings
- Salesforce Developers, Second-Generation Managed Packaging Developer Guide, Components Available in Managed Packages
- Salesforce Developers, ISVforce Guide, Secure Your Connected Apps and External Client Apps



