Authentication
Salesforce Toolkit supports multiple authentication methods to connect to Salesforce. This guide will help you choose the right authentication method for your use case.
Quick Reference
Here’s a quick reference table of available authentication methods:
Method |
Use case |
|---|---|
CLI Authentication |
Local development with Salesforce CLI installed |
OAuth Username-Password |
Legacy scripts; prefer a headless integration flow for production |
OAuth JWT Bearer |
Server-to-server integration with a signing key |
OAuth Client Credentials |
Service integration as a configured Run As user |
SOAP Security Token |
Legacy applications needing password and security-token authentication |
SOAP IP Filtering |
Orgs with IP restrictions enabled |
Lazy Authentication (Auto-selection)
For most use cases, you can use the lazy_login function which automatically selects the appropriate authentication method based on the provided parameters:
from sf_toolkit import SalesforceClient, lazy_login
# CLI Authentication
client = SalesforceClient(login=lazy_login(sf_cli_alias="my-org"))
# OAuth JWT Bearer Flow
with open("private_key.pem", "rb") as f:
private_key_data = f.read()
client = SalesforceClient(
login=lazy_login(
username="user@example.com",
consumer_key="your_consumer_key",
private_key=private_key_data
)
)
# Username-Password Flow
client = SalesforceClient(
login=lazy_login(
username="user@example.com",
password="password",
consumer_key="your_consumer_key",
consumer_secret="your_consumer_secret"
)
)
CLI-based Authentication
If you’re using the Salesforce CLI (sf or sfdx), this is the simplest method for local development:
from sf_toolkit import SalesforceClient, cli_login
# Use default org from CLI
client = SalesforceClient(login=cli_login())
# Use a specific org by alias or username
client = SalesforceClient(login=cli_login(alias_or_username="my-dev-org"))
# Specify the path to the CLI executable
client = SalesforceClient(login=cli_login(sf_exec_path="/custom/path/to/sf"))
This method:
Uses the existing authentication from your Salesforce CLI
Doesn’t require storing credentials in your code
Works with any authentication method supported by the CLI
Automatically handles token refresh
OAuth 2.0 Authentication
Salesforce Toolkit supports several OAuth 2.0 flows for different use cases:
The table above is a starting point, not a guarantee of security. Use a dedicated
integration identity, least-privilege permissions, protected secrets, and a
rotation policy. OAuth scopes do not grant permissions the user lacks. Prefer an
explicit login factory when the flow is known; lazy_login selects by the
presence of credential fields, so extra fields can change its selection.
Username-Password Flow
For simple scripting and personal applications:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import password_login
client = SalesforceClient(
login=password_login(
username="user@example.com",
password="password",
consumer_key="your_consumer_key",
consumer_secret="your_consumer_secret",
domain="login" # or your custom domain
)
)
Warning
This method requires storing your password in your code or configuration. Consider using other methods for production applications.
JWT Bearer Flow
For secure server-to-server integration:
import pathlib
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import public_key_auth_login
# Load private key
private_key_path = pathlib.Path("path/to/private_key.key")
private_key = private_key_path.read_bytes()
client = SalesforceClient(
login=public_key_auth_login(
username="user@example.com",
consumer_key="your_connected_app_consumer_key",
private_key=private_key,
domain="login" # or your custom domain
)
)
This method:
Does not require storing user passwords
Uses digital signatures to securely authenticate
Is ideal for automated applications and server-to-server integrations
Requires a connected app with a digital certificate
Encrypted keys and reusable app credentials
Install sf-toolkit[jwt]. The factory accepts PKCS#8/traditional PEM,
OpenSSH RSA private keys, or an already loaded cryptography RSAPrivateKey.
RSA keys must be at least 2048 bits; 3072 and 4096 bits are supported. Key
material is the file contents, not a filename. Encrypted material takes
private_key_passphrase as bytes or text:
import os
from pathlib import Path
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import public_key_auth_login
# The app/key may be shared; bind the exact Salesforce username explicitly.
login = public_key_auth_login(
username=os.environ["SF_USERNAME"],
consumer_key=os.environ["SF_CONSUMER_KEY"],
private_key=Path(os.environ["SF_JWT_KEY_FILE"]).read_bytes(),
private_key_passphrase=os.environ["SF_JWT_KEY_PASSPHRASE"],
domain="company--uat.sandbox.my.salesforce.com",
)
client = SalesforceClient(login=login, api_version=66)
try:
client.get("/services/oauth2/userinfo")
finally:
client.close()
lazy_login forwards private_key_passphrase too. Alternatively, use
sf_toolkit.auth.load_private_key(material, passphrase) and pass the returned
RSA key object without a passphrase. Decrypted keys stay in memory and are not
written to disk. Never log the input key, passphrase, or token.
External Client App setup and certificate lifecycle
In Salesforce External Client App Manager, enable OAuth, the api scope,
and JWT Bearer Flow. Upload the public certificate, never the private key.
Pre-authorize the integration user through the app policy and an assigned
permission set. Use the Consumer Key as consumer_key; JWT bearer does not
need a Consumer Secret. Follow Salesforce’s current setup guidance for your org:
External Client App authorization.
The RSA key itself has no expiry, but its X.509 certificate does. Same-key certificate renewal extends certificate validity; it is not private-key rotation. Renew before expiration, rotate compromised/aging keys separately, and retain independent recovery access. The toolkit supplies Metadata API primitives, not a renewal scheduler or secret store. Some OAuth settings are not exposed through metadata, so preserving returned XML does not guarantee that updating it preserves every Salesforce security policy.
After changing a certificate, verify with a new client and no cached token so success establishes a fresh JWT login. Use a separate connection name if the old client is still open; do not mutate a live client’s credentials.
Local cryptographic tests verify key loading and assertion construction, not Salesforce’s acceptance of a JWT audience for every login/My Domain/sandbox configuration. Validate audience behavior against the intended provider endpoint in a sandbox; no audience policy change is inferred from local tests alone.
Client Credentials Flow
For service-to-service integration as a designated Salesforce Run As user:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import client_credentials_flow_login
client = SalesforceClient(
login=client_credentials_flow_login(
consumer_key="your_consumer_key",
consumer_secret="your_consumer_secret",
domain="company.my.salesforce.com"
)
)
This method:
Salesforce selects the user through the app’s Run As policy, not a username parameter
Requires an External Client App (or existing Connected App) configured for client credentials
Is useful for background service integrations
Use the org-specific My Domain hostname, not login.salesforce.com or
test.salesforce.com. For a sandbox this commonly resembles
company--uat.sandbox.my.salesforce.com. Pass only the hostname, without
https:// or a path. JWT/password flows also accept login/test
shorthand where permitted by the org. Allow configuration changes to propagate
before testing.
For an External Client App, enable Client Credentials Flow in both OAuth
Settings and Policies, configure the dedicated Run As integration user, and
copy the Consumer Key/Secret into protected configuration. When using
lazy_login, omit username, password, and private_key for this
flow. Scopes and the Run As user’s permissions must both permit the operation.
SOAP Authentication
Salesforce Toolkit supports various SOAP-based authentication methods for compatibility with different security configurations:
Security Token Authentication
For orgs that require a security token with the password:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import security_token_login
client = SalesforceClient(
login=security_token_login(
username="user@example.com",
password="password",
security_token="your_security_token",
client_id="YourAppName", # Optional identifier for your app
domain="login", # Or your custom domain
api_version=63.0 # Salesforce API version
)
)
IP Filtering Authentication
For orgs with IP filtering enabled that allow specific IPs to skip the security token:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import ip_filtering_non_service_login
client = SalesforceClient(
login=ip_filtering_non_service_login(
username="user@example.com",
password="password",
client_id="YourAppName", # Optional
domain="login", # Or your custom domain
api_version=63.0 # Salesforce API version
)
)
Organization-Scoped Login
For logging in to a specific organization within a multi-org setup:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import ip_filtering_org_login
client = SalesforceClient(
login=ip_filtering_org_login(
username="user@example.com",
password="password",
organizationId="00Dxxxxxxxxxx", # Your org ID
client_id="YourAppName", # Optional
domain="login", # Or your custom domain
api_version=63.0 # Salesforce API version
)
)
Using Tokens Directly
If you already have a Salesforce access token and instance URL:
from sf_toolkit import SalesforceClient
from sf_toolkit.auth import SalesforceToken
from httpx import URL
# Create a token directly
token = SalesforceToken(
instance=URL("https://myinstance.my.salesforce.com"),
token="00D..." # Your access token
)
# Use the token
client = SalesforceClient(token=token)
Token Refresh and Callbacks
You can register a callback function to be executed when a token is refreshed:
def token_updated(token):
# Save token to database or file
print(f"Token updated for {token.instance}")
with open("token.txt", "w") as f:
f.write(f"{token.instance}|{token.token}")
client = SalesforceClient(
login=cli_login(),
token_refresh_callback=token_updated
)
Best Practices
Don’t hardcode credentials: Store secrets in environment variables or a secure credential store.
import os client = SalesforceClient( login=password_login( username=os.environ["SF_USERNAME"], password=os.environ["SF_PASSWORD"], consumer_key=os.environ["SF_CONSUMER_KEY"], consumer_secret=os.environ["SF_CONSUMER_SECRET"] ) )
Use the strongest authentication method available: - JWT Bearer for server applications - CLI login for development - Avoid storing passwords in code
Implement token persistence to avoid unnecessary authentications:
import os import json from httpx import URL from sf_toolkit import SalesforceClient from sf_toolkit.auth import SalesforceToken, cli_login # Try to load saved token token = None token_file = "saved_token.json" if os.path.exists(token_file): try: with open(token_file, "r") as f: data = json.load(f) token = SalesforceToken( instance=URL(data["instance"]), token=data["token"] ) except Exception as e: print(f"Error loading token: {e}") # Save token on refresh def save_token(token): with open(token_file, "w") as f: json.dump({ "instance": str(token.instance), "token": token.token }, f) # Create client with token or login method client = SalesforceClient( login=None if token else cli_login(), token=token, token_refresh_callback=save_token )
Handle token expiration gracefully: Salesforce Toolkit automatically attempts to refresh tokens when they expire during a request.
Authentication Classes
Under the hood, these authentication methods use these core classes:
SalesforceAuth- HTTPX authentication class that handles token management and refreshSalesforceToken- Named tuple that represents a Salesforce access token with instance URLSalesforceLogin- A callable that performs the authentication flow and returns a tokenTokenRefreshCallback- A callable type for token refresh callbacks