Authentication Setup
This skill uses JWT Bearer authentication to access the Data Cloud Query API. Authentication is configured via an External Client App (ECA) in Salesforce.
Prerequisites
- Salesforce CLI installed and authenticated to your org
- OpenSSL for certificate generation
- Data Cloud enabled in your org
- System Administrator profile (or appropriate permissions for ECA setup)
Quick Setup (5 Steps)
Step 1: Generate JWT Certificate
# Create directory for JWT keys
mkdir -p ~/.sf/jwt
# Generate private key and self-signed certificate (valid 1 year)
# Naming convention: {org_alias}-agentforce-observability.key
openssl req -x509 -sha256 -nodes -days 365 \
-newkey rsa:2048 \
-keyout ~/.sf/jwt/Vivint-DevInt-agentforce-observability.key \
-out ~/.sf/jwt/Vivint-DevInt-agentforce-observability.crt \
-subj "/CN=AgentforceObservability/O=Vivint"
# Secure the private key (required - Salesforce rejects world-readable keys)
chmod 600 ~/.sf/jwt/Vivint-DevInt-agentforce-observability.key
Step 2: Create External Client App
In Salesforce Setup:
- Setup → External Client App Manager → New External Client App
- Fill in the basic details:
| Field | Value |
|---|---|
| Name | Agentforce Observability |
| API Name | Agentforce_Observability |
| Description | JWT Bearer auth for Agentforce STDM extraction via Claude Code |
| Distribution State | Local |
- Click Save
Step 3: Configure OAuth Settings
In the ECA → OAuth Settings tab:
| Setting | Value |
|---|---|
| Enable OAuth | ✅ Checked |
| Callback URL | https://login.salesforce.com/services/oauth2/callback |
| Selected OAuth Scopes | cdp_query_api, refresh_token, offline_access |
| Require PKCE | ❌ Unchecked (not needed for JWT Bearer) |
| Enable Client Credentials Flow | ❌ Optional |
Upload Certificate:
- Check Use digital signatures
- Click Choose File
- Upload
~/.sf/jwt/{org}-agentforce-observability.crt - Click Save
Step 4: Configure App Policies
In the ECA → Policies tab:
| Setting | Value |
|---|---|
| Permitted Users | Admin approved users are pre-authorized |
| IP Relaxation | Relax IP restrictions (for CLI usage) |
Add Your User:
- Click Manage → Manage Profiles or Manage Permission Sets
- Add your user's profile or an appropriate permission set
- Click Save
Step 5: Get Consumer Key & Test
- Go to ECA → OAuth Settings tab
- Copy the Consumer Key (starts with
3MVG9...) - Test authentication:
# Option 1: Pass consumer key directly
python3 scripts/cli.py test-auth \
--org Vivint-DevInt \
--consumer-key "3MVG9..."
# Option 2: Use environment variable
export SF_CONSUMER_KEY="3MVG9..."
python3 scripts/cli.py test-auth --org Vivint-DevInt
Expected output:
Testing Authentication
Org: Vivint-DevInt
Key: /Users/you/.sf/jwt/Vivint-DevInt-agentforce-observability.key
Getting org info...
Instance: https://vivint--devint.sandbox.my.salesforce.com
Username: your.user@vivint.com.devint
Sandbox: True
Testing token generation...
✓ Token generated
Testing Data Cloud access...
✓ Data Cloud accessible
Authentication successful!
Key Path Resolution
The CLI resolves the private key path in this order:
- Explicit
--key-pathargument (highest priority) - App-specific key:
~/.sf/jwt/{org_alias}-agentforce-observability.key - Generic org key:
~/.sf/jwt/{org_alias}.key(fallback)
Examples
# Uses app-specific key automatically
python3 scripts/cli.py test-auth --org Vivint-DevInt --consumer-key "..."
# → Resolves to: ~/.sf/jwt/Vivint-DevInt-agentforce-observability.key
# Explicit key path (overrides all defaults)
python3 scripts/cli.py test-auth --org Vivint-DevInt \
--consumer-key "..." \
--key-path ~/.sf/jwt/custom-key.key
File Locations
| File | Location | Description |
|---|---|---|
| Private Key | ~/.sf/jwt/{org}-agentforce-observability.key |
RSA private key (chmod 600) |
| Certificate | ~/.sf/jwt/{org}-agentforce-observability.crt |
X.509 cert uploaded to Salesforce |
| Consumer Key | $SF_CONSUMER_KEY or --consumer-key |
From ECA OAuth Settings |
Required OAuth Scopes
| Scope | Purpose | Required |
|---|---|---|
cdp_query_api |
Execute Data Cloud SQL queries | ✅ Yes |
refresh_token, offline_access |
Server-to-server access | ✅ Yes |
cdp_profile_api |
Access profile and DMO metadata | Optional |
Troubleshooting
invalid_grant Error
RuntimeError: Token exchange failed: invalid_grant
Causes & Fixes:
| Cause | Fix |
|---|---|
| Certificate mismatch | Re-upload .crt file to ECA |
| Expired certificate | Regenerate with openssl (see Step 1) |
| User not authorized | Add user to ECA policies (see Step 4) |
| Wrong login URL | Verify sandbox detection is working |
Verify certificate expiry:
openssl x509 -enddate -noout -in ~/.sf/jwt/Vivint-DevInt-agentforce-observability.crt
403 Forbidden
RuntimeError: Access denied: Ensure ECA has cdp_query_api scope
Fix: Add cdp_query_api scope to the ECA OAuth Settings.
Key Not Found
FileNotFoundError: Private key not found at ~/.sf/jwt/myorg.key
Causes:
- Key file doesn't exist → Generate with Step 1
- Wrong org alias → Check
sf org listfor correct alias - Using old naming convention → Rename to
{org}-agentforce-observability.key
Permission Denied on Key
PermissionError: [Errno 13] Permission denied: '~/.sf/jwt/...'
Fix:
chmod 600 ~/.sf/jwt/*.key
Sandbox vs Production
The skill automatically detects sandbox orgs:
- Reads
isSandboxfromsf org display --json - Uses
https://test.salesforce.comfor token exchange (sandboxes) - Uses
https://login.salesforce.comfor production
No additional configuration needed.
Security Best Practices
- Protect private keys: Always
chmod 600 ~/.sf/jwt/*.key - Rotate certificates annually: Regenerate before expiration
- Use separate ECAs: One per org/environment for isolation
- Never commit keys: Add
*.keyto.gitignore - Audit access: Review ECA usage in Setup → Security → Connected Apps OAuth Usage
Environment Variables
For automation/CI, set these environment variables:
# Consumer key (org-specific takes priority)
export SF_VIVINT_DEVINT_CONSUMER_KEY="3MVG9..."
# or generic fallback
export SF_CONSUMER_KEY="3MVG9..."
The CLI checks in this order:
--consumer-keyargumentSF_{ORG_ALIAS}_CONSUMER_KEY(uppercase, hyphens to underscores)SF_CONSUMER_KEY
See Also
- sf-connected-apps skill - General ECA patterns
- CLI Reference - All command options
- Troubleshooting - More error solutions