---
cuppy_hub: salesforce
cuppy_path: reference/auth/external-client-app-as-source.md
cuppy_section: docs
cuppy_doc: 3TMQ-HWBB
cuppy_doc_uuid: 47b7ff6b-2dc1-47fa-9235-e98f552a3199
cuppy_permalink: https://cuppy.io/salesforce/d/3TMQ-HWBB
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/salesforce/docs/reference/auth/external-client-app-as-source
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 707ef6aae637a63766bcb7f7f9d2afaca29e731c12399b4fd6375b5caed47dd8
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# External Client Apps as source

An ECA is several metadata components that point at one another by name. This is the set Salesforce's CLI generator writes, for an ECA that signs users in with the authorization code flow and PKCE and needs no client secret:

```xml
<!-- externalClientApps/Agent_Chat_Web.eca-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ExternalClientApplication xmlns="http://soap.sforce.com/2006/04/metadata">
    <contactEmail>platform-team@<example></contactEmail>
    <description>Web chat front end (OAuth auth code + PKCE, no client secret).</description>
    <distributionState>Local</distributionState>
    <label>Agent_Chat_Web</label>
</ExternalClientApplication>
```

```xml
<!-- extlClntAppGlobalOauthSets/Agent_Chat_Web.ecaGlblOauth-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ExtlClntAppGlobalOauthSettings xmlns="http://soap.sforce.com/2006/04/metadata">
    <callbackUrl>https://chat.example.com/oauth/callback</callbackUrl>
    <externalClientApplication>Agent_Chat_Web</externalClientApplication>
    <isConsumerSecretOptional>true</isConsumerSecretOptional>
    <label>Agent_Chat_Web Global OAuth</label>
</ExtlClntAppGlobalOauthSettings>
```

```xml
<!-- extlClntAppOauthSettings/Agent_Chat_Web.ecaOauth-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ExtlClntAppOauthSettings xmlns="http://soap.sforce.com/2006/04/metadata">
    <externalClientApplication>Agent_Chat_Web</externalClientApplication>
    <label>Agent_Chat_Web OAuth Settings</label>
    <commaSeparatedOauthScopes>Web</commaSeparatedOauthScopes>
</ExtlClntAppOauthSettings>
```

| File (folder, suffix) | Holds |
|---|---|
| `ExternalClientApplication` (`externalClientApps`, `.eca`) | Name, contact, description, `distributionState` (`Local` for an app used only in this org) |
| `ExtlClntAppGlobalOauthSettings` (`extlClntAppGlobalOauthSets`, `.ecaGlblOauth`) | Callback URL, whether a consumer secret is optional |
| `ExtlClntAppOauthSettings` (`extlClntAppOauthSettings`, `.ecaOauth`) | Scopes, comma-separated, as scope names (the generator uses `Web`) |
| `ExtlClntAppOauthConfigurablePolicies` (`extlClntAppOauthPolicies`, `.ecaOauthPlcy`) and `ExtlClntAppConfigurablePolicies` (`extlClntAppPolicies`, `.ecaPlcy`) | Admin policies: permitted users, Run As user, IP relaxation, refresh token and session policies |

## What not to put in source

- **The consumer key and secret.** They're generated by the org, read once in Setup (**Settings → OAuth Settings → Consumer Key and Secret**, after an email code) and kept in your secret store. Every org, including each sandbox and scratch org, has its own.
- **Guessed field names.** Salesforce's generator only shows the fields above. For the client credentials flow, JWT bearer, a Run As user or the Agent API scopes, configure the app once in Setup (`reference/auth/external-client-apps-and-oauth-flows.md`), then retrieve it, so the policy files hold exactly what the org wrote:

`sf project retrieve start --metadata ExternalClientApplication:Orders_Integration --metadata ExtlClntAppOauthSettings:Orders_Integration --metadata ExtlClntAppOauthConfigurablePolicies:Orders_Integration --target-org dev`

The hub's reading: name every component after the app, as the generator does. A retrieve that returns differently named child components shows the names to use. Deploying the files to another org creates a new app with new keys there.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 376 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/salesforce/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
