Expert in creating and managing Salesforce Connected Apps and External Client Apps (ECAs) with OAuth configuration, security best practices, and metadata compliance.
Core Responsibilities
-
Connected App Generation: Create Connected Apps with OAuth 2.0 configuration, scopes, and callbacks
-
External Client App Generation: Create ECAs with modern security model and separation of concerns
-
Security Review: Analyze OAuth configurations for security best practices
-
Validation & Scoring: Score apps against 6 categories (0-120 points)
-
Migration Guidance: Help migrate from Connected Apps to External Client Apps
Workflow (5-Phase Pattern)
Phase 1: Requirements Gathering
Use AskUserQuestion to gather:
| 1 | App Type | Connected App / External Client App
| 2 | OAuth Flow | Authorization Code, JWT Bearer, Device, Client Credentials
| 3 | Use Case | API Integration, SSO, Mobile, CI/CD
| 4 | Scopes | api, refresh_token, full, web, etc.
| 5 | Distribution | Local / Packageable (multi-org)
Then:
-
Check existing:
Glob: **/*.connectedApp-meta.xml,Glob: **/*.eca-meta.xml -
Create TodoWrite tasks
Phase 2: App Type Selection
| Single Org | ✓ Good | ✓ Good
| Multi-Org | ⚠️ Manual | ✓ 2GP Packaging
| Secret Mgmt | ⚠️ Visible | ✓ Hidden in sandboxes
| Key Rotation | ⚠️ Manual | ✓ API-driven
| Audit Trail | ⚠️ Limited | ✓ MFA + audit
| API Version | Any | 61.0+ required
Quick Decision:
-
Multi-org or ISV → External Client App
-
Regulated industry → External Client App (audit requirements)
-
Simple single-org → Connected App sufficient
-
Automated DevOps → External Client App (key rotation)
Phase 3: Template Selection & Generation
Template Locations (try in order):
-
~/.claude/plugins/marketplaces/sf-skills/sf-connected-apps/templates/[template] -
[project-root]/sf-connected-apps/templates/[template]
Template Selection:
| Connected App (Basic)
| connected-app-basic.xml
| Minimal OAuth
| Connected App (Full)
| connected-app-oauth.xml
| Web Server Flow
| Connected App (JWT)
| connected-app-jwt.xml
| Server-to-Server
| Connected App (Canvas)
| connected-app-canvas.xml
| Canvas Apps
| External Client App
| external-client-app.xml
| Base ECA
| ECA OAuth (Global)
| eca-global-oauth.xml
| Global settings
| ECA OAuth (Instance)
| eca-oauth-settings.xml
| Per-org settings
Output Locations:
-
Connected Apps:
force-app/main/default/connectedApps/ -
External Client Apps:
force-app/main/default/externalClientApps/
Phase 4: Security Validation & Scoring
Scoring Categories:
Score: XX/120 ⭐⭐⭐⭐
├─ Security: XX/30 (PKCE, token rotation, IP restrictions, certificates)
├─ OAuth Config: XX/25 (callbacks, flows, token expiration, OIDC)
├─ Metadata: XX/20 (required fields, API version, naming)
├─ Best Practices: XX/20 (minimal scopes, named principal, pre-auth)
├─ Scopes: XX/15 (least privilege, no deprecated)
└─ Documentation: XX/10 (description, contact email)
Thresholds:
| 80-120 | ✅ Deploy | Production-ready
| 54-79 | ⚠️ Review | May need hardening
| <54 | ❌ Block | Security risk - fix first
📋 Detailed scoring: See Phase 4 in previous version for point breakdown per criteria.
Phase 5: Deployment & Documentation
Deploy:
Skill(skill="sf-deploy", args="Deploy connected apps to [target-org] with --dry-run")
Completion Output:
✓ App Created: [AppName]
Type: [Connected App | External Client App]
Location: force-app/main/default/[connectedApps|externalClientApps]/
OAuth Flow: [flow]
Scopes: [list]
Score: XX/120
Next Steps:
- Retrieve Consumer Key from Setup > App Manager
- Test OAuth flow (Postman/curl)
- For ECA: Configure policies in subscriber org
Quick Reference: OAuth Flow Selection
| Web Backend
| Authorization Code
| Optional
| Yes
| connected-app-oauth.xml
| SPA/Mobile
| Authorization Code
| Required
| No
| external-client-app.xml
| Server-to-Server
| JWT Bearer
| N/A
| Certificate
| connected-app-jwt.xml
| CI/CD
| JWT Bearer
| N/A
| Certificate
| connected-app-jwt.xml
| CLI/IoT
| Device
| N/A
| No
| connected-app-basic.xml
| Service Account
| Client Credentials
| N/A
| Yes
| eca-oauth-settings.xml (ECA only)
📘 Detailed flows: See resources/oauth-flows-reference.md for implementation patterns, security checklists, and code examples.
Metadata Structure Essentials
Connected App XML
<?xml version="1.0" encoding="UTF-8"?>
<ConnectedApp xmlns="http://soap.sforce.com/2006/04/metadata">
<label>My Integration App</label>
<contactEmail>admin@company.com</contactEmail>
<description>Integration description</description>
<!-- OAuth Configuration -->
<oauthConfig>
<callbackUrl>https://app.example.com/oauth/callback</callbackUrl>
<certificate>MyCertificate</certificate> <!-- JWT Bearer only -->
<scopes>Api</scopes>
<scopes>RefreshToken</scopes>
<isAdminApproved>true</isAdminApproved>
<isConsumerSecretOptional>false</isConsumerSecretOptional>
<isPkceRequired>true</isPkceRequired> <!-- Public clients -->
</oauthConfig>
<!-- OAuth Policy -->
<oauthPolicy>
<ipRelaxation>ENFORCE</ipRelaxation>
<refreshTokenPolicy>infinite</refreshTokenPolicy>
<isRefreshTokenRotationEnabled>true</isRefreshTokenRotationEnabled>
</oauthPolicy>
</ConnectedApp>
External Client App Files
1. Header File ([AppName].eca-meta.xml):
<ExternalClientApplication xmlns="http://soap.sforce.com/2006/04/metadata">
<label>My External Client App</label>
<contactEmail>admin@company.com</contactEmail>
<description>Modern integration</description>
<distributionState>Local</distributionState> <!-- or Packageable -->
</ExternalClientApplication>
2. Global OAuth ([AppName].ecaGlblOauth-meta.xml):
<ExtlClntAppGlobalOauthSettings xmlns="http://soap.sforce.com/2006/04/metadata">
<callbackUrl>https://app.example.com/oauth/callback</callbackUrl>
<externalClientApplication>My_App_Name</externalClientApplication>
<label>Global OAuth Settings</label>
<isPkceRequired>true</isPkceRequired>
<isConsumerSecretOptional>true</isConsumerSecretOptional>
</ExtlClntAppGlobalOauthSettings>
⚠️ Important: File suffix is .ecaGlblOauth (abbreviated), NOT .ecaGlobalOauth
3. Instance OAuth ([AppName].ecaOauth-meta.xml):
<ExtlClntAppOauthSettings xmlns="http://soap.sforce.com/2006/04/metadata">
<externalClientApplication>My_App_Name</externalClientApplication>
<commaSeparatedOauthScopes>api,refresh_token</commaSeparatedOauthScopes>
<label>Instance OAuth Settings</label>
<isClientCredentialsEnabled>false</isClientCredentialsEnabled>
</ExtlClntAppOauthSettings>
OAuth Scopes Reference
| Access and manage your data
| Api
| REST/SOAP API access
| Perform requests at any time
| RefreshToken
| Offline access
| Full access
| Full
| Complete access (use sparingly)
| Access your basic information
| OpenID
| OpenID Connect
| Web access
| Web
| Web browser access
| Access Chatter
| ChatterApi
| Chatter REST API
| Access custom permissions
| CustomPermissions
| Custom permissions
| Access Einstein Analytics
| Wave
| Analytics API
Security Best Practices
| Wildcard callback | Token hijacking | Specific URLs | -10 points
| Full scope everywhere
| Over-privileged
| Minimal scopes
| -15 points
| No token expiration | Long-term compromise | Set expiration | -5 points
| Secret in code | Credential leak | Named Credentials | -15 points
| PKCE disabled (mobile) | Code interception | Enable PKCE | -10 points
| No IP restrictions | Unauthorized access | Configure IP ranges | -5 points
🔒 Security details: See docs/security-checklist.md for comprehensive security review.
Scratch Org Setup (External Client Apps)
{
"orgName": "ECA Development Org",
"edition": "Developer",
"features": [
"ExternalClientApps",
"ExtlClntAppSecretExposeCtl"
]
}
Common CLI Commands
# List Connected Apps in org
sf org list metadata --metadata-type ConnectedApp --target-org [alias]
# Retrieve Connected App
sf project retrieve start --metadata ConnectedApp:[AppName] --target-org [alias]
# Deploy
sf project deploy start --source-dir force-app/main/default/connectedApps --target-org [alias]
# Retrieve Consumer Key (after deployment)
# Go to Setup > App Manager > [App] > View
Migration: Connected App → External Client App
Quick Steps:
-
Assess:
Glob: **/*.connectedApp-meta.xml -
Create: Map OAuth settings to ECA structure
-
Parallel: Deploy ECA alongside old app
-
Test: Verify flows with new Consumer Key
-
Cutover: Update integrations, disable old app
-
Archive: Remove after 30-day grace period
Scoring Benefit: ECAs typically score 15-20 points higher.
📘 Detailed migration: See docs/migration-guide.md for step-by-step process.
Cross-Skill Integration
| sf-metadata
| Named Credentials for callouts
| Skill(skill="sf-metadata") → "Create Named Credential"
| sf-deploy
| Deploy to org
| Skill(skill="sf-deploy", args="Deploy to [org]")
| sf-apex
| OAuth token handling
| Skill(skill="sf-apex") → "Create token refresh service"
Key Insights
| ECA vs Connected App | ECAs provide better secret management and 2GP packaging | Phase 2 Decision Matrix
| PKCE for Public Clients | Always required for mobile/SPA apps | resources/oauth-flows-reference.md
| JWT Bearer for CI/CD | Server-to-server auth without user interaction | resources/oauth-flows-reference.md
| Token Rotation | Enable for SPAs to prevent token reuse | resources/oauth-flows-reference.md
| Named Credentials | Store secrets securely, automatic refresh | resources/oauth-flows-reference.md
| Minimal Scopes | Use least privilege (api instead of full) | Phase 4 Scoring
| IP Restrictions | Add when integration has known IP ranges | Phase 4 Scoring
| Certificate Auth | Stronger than username/password for JWT | resources/oauth-flows-reference.md
Notes
-
API Version: 62.0+ recommended, 61.0+ required for External Client Apps
-
Scoring: Block deployment if score < 54 (54% threshold)
-
Consumer Secret: Never commit to version control - use environment variables
-
External Client Apps: Preferred for new development (modern security model)
-
Testing: Use Postman for OAuth flow testing before production
Additional Resources
Detailed References
- OAuth Flow Patterns: resources/oauth-flows-reference.md
Implementation examples (Node.js, Python, JavaScript)
-
Security checklists per flow
-
Error handling patterns
-
Named Credentials integration
Documentation
-
OAuth Flow Diagrams: docs/oauth-flows.md
-
Security Review: docs/security-checklist.md
-
Migration Guide: docs/migration-guide.md
-
Testing & Validation: docs/testing-validation-guide.md
Examples
- Usage Examples: examples/example-usage.md
License
MIT License. See LICENSE file. Copyright (c) 2024-2025 Jag Valaiyapathy