SfSkills Domains Docs GitHub

Home / integration / oauth-flows-and-connected-apps

oauth-flows-and-connected-apps

Use when choosing or reviewing Salesforce OAuth flows and connected-app policy for integrations, including client credentials, JWT bearer, authorization code, device flow, scopes, and token lifecycle controls.

Open the skill folder on GitHub


Oauth Flows And Connected Apps

Use this skill when the success or failure of an integration depends on picking the right trust model up front. OAuth flow choice is not protocol trivia. It determines whether the integration respects user context, how secrets rotate, how outages behave when tokens expire, and whether security review becomes easy or painful.


Before Starting

Gather this context before working on anything in this domain:

Questions to Ask Before Configuring

QuestionWhy it mattersWhat a good answer addsWhat proper configuration adds over just doing it
"Does a human user authorize the access, or is this system-to-system?"Delegated access needs the web server flow (with PKCE); system access uses client credentials or JWT bearerThe flow familyTokens that carry the right identity, so audit logs show who acted
"If system-to-system, which Salesforce user should the integration act as, and what is that user allowed to do?"Client credentials returns tokens for one execution user; JWT bearer issues them for the user in sub after prior approvalA dedicated integration user and its permission setsLeast privilege that survives scope mistakes
"Who manages certificates and secret rotation, and how often?"JWT bearer needs an X.509 certificate on the app; client credentials depends on a consumer secret anyone holding it can useA rotation owner and scheduleA planned rotation instead of an outage or a leaked secret that keeps working
"Will this app be packaged, promoted across sandboxes, or kept in source control?"External client apps are metadata-compliant and support 2GP; local ones are not copied to new sandboxes; global OAuth settings hold secrets that must stay out of source controlConnected app vs external client app, and a promotion planRepeatable deployments without secrets in git
"Which org-wide flows must be blocked?"Orgs created Summer '23 or later block username-password by default; blocking a flow breaks every existing integration that uses itThe OauthOidcSettings target state, tested in a sandboxA hardened org that does not surprise the integrations already running
"What scopes does the consumer really need?"Scopes cannot be requested on the token call for client credentials or JWT; they come from the app configurationThe minimal scope list on the appTokens that cannot reach data the integration never needed

What a proper configuration adds over "just creating a connected app": the flow matches the actor, the principal behind the token is least-privilege, secrets and certificates have an owner and a rotation date, and insecure flows are blocked org-wide without breaking anything that still depends on them.


Core Concepts

Flow Choice Starts With Identity

Use Authorization Code when a user must grant access and their permissions matter. Use Client Credentials or JWT bearer when the workload is system-to-system. Device flow is for constrained-user-input experiences, not a shortcut around better integration design.

FlowGrant / token endpoint callRefresh tokenWho the token representsKey constraint (Identity guide)
Web serverauthorization_code, recommended with PKCEYes, per app policyThe authorizing userThe web server must protect the client secret
JWT bearerurn:ietf:params:oauth:grant-type:jwt-bearer with a signed assertionNever issuedThe user in subRS256 with an uploaded certificate (4 KB max); requires prior approval; scopes cannot be passed; 3-minute clock-skew buffer on exp
Client credentialsclient_credentials with consumer key and secret (body or Basic header)Not supportedThe configured execution (integration) userScopes cannot be passed on the token call; full, web, and refresh_token are filtered out
DeviceDevice authorization, user approves on a second devicePer policyThe approving userFor limited-input devices and command-line apps
Token exchangeExchange an external IdP token for a Salesforce tokenPer policyThe mapped userFor architectures with a central identity provider
User-agentImplicit grantNot recommendedThe userSalesforce recommends blocking it; blocking also blocks the hybrid app token flow
Username-passwordpasswordNot recommendedThe user whose password is storedBlocked by default in orgs created Summer '23 or later; not supported by external client apps

Connected Apps and External Client Apps

The Identity guide recommends external client apps "in all situations" and migrating local connected apps to local external client apps, while noting some features remain connected-app only.

ConcernConnected appExternal client app
Packaging1GP; 2GP only by reference2GP, with distribution states
Metadata APISubset through ConnectedAppFull: ExternalClientApplication plus OAuth settings and policy types
Sandbox clone or refreshCopiedLocal apps are not copied; only packaged ones are
Username-password flowSupported (if not blocked)Not supported
Dynamic client registrationSupportedStill in development
Secrets in metadataconsumerKey / consumerSecret on ConnectedAppOauthConfigOnly in ExtlClntAppGlobalOauthSettings, which "can't be packaged and must not be added to source control"

Connected App Policy Is Part Of The Architecture

A connected app is not just a client ID. Scopes, token settings, IP rules, and ownership determine how the integration behaves operationally and under incident response.

Integration Principals Need Least Privilege

Even a perfect OAuth flow is unsafe if the integration user has broad object access or sysadmin-level power. The flow and the permission model must line up.

Token Lifecycle Is An Operations Problem

Rotation, revocation, monitoring repeated auth failures, and handling invalid_grant should be decided before production, not during the first outage.


Common Patterns

Client Credentials For Server-To-Server Access

When to use: A system needs Salesforce API access and no end-user context is required.

How it works: Use an external client app (or a connected app) with the client credentials flow enabled, an execution user dedicated to the integration, and narrow scopes and permission sets.

Why not the alternative: Username-password flow is weaker operationally and worse for security review.

JWT Bearer For Certificate-Managed Server Auth

When to use: The organization has mature certificate management and wants server authentication without interactive consent.

How it works: The external system signs the assertion and exchanges it for access under a controlled principal.

Authorization Code For Delegated Access

When to use: A user must explicitly authorize the app and user-level access should be preserved.

How it works: The app obtains consent, receives an authorization code, and manages the token lifecycle according to policy.


Decision Guidance

SituationRecommended ApproachReason
Machine-to-machine integration into SalesforceClient Credentials or JWT bearerNo end-user context required
Enterprise-grade server auth with certificate operations already in placeJWT bearerStrong fit for managed key posture
User authorizes an app to act on their behalfAuthorization CodePreserves user context and consent
Legacy proposal uses username and passwordUsually rejectPoor security and operability compared with OAuth-based patterns

  1. Classify the actor (human-delegated or system) and the direction of traffic, then pick the flow from the Core Concepts table.
  2. Decide connected app or external client app using the comparison table; default to an external client app unless a connected-app-only feature is required.
  3. Create the integration principal: a dedicated user with only the permission sets the integration needs (the client credentials execution user must have the API Only permission per the Metadata API guide).
  4. Configure the app: minimal OAuth scopes, permitted users set to admin-approved with a permission set, refresh token policy, IP policy, PKCE for authorization code flows, certificate or secret ownership. Use 0 for deployable files.
  5. Harden the org: set OauthOidcSettings to block username-password and user-agent flows after confirming in a sandbox that no integration still uses them.
  6. Run python3 skills/integration/oauth-flows-and-connected-apps/scripts/check_oauth_flows_and_connected_apps.py --manifest-dir <project> and resolve every finding.
  7. Rehearse rotation and revocation: rotate the consumer secret or certificate in a sandbox and confirm the integration recovers.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

One-line summaries; the full entries are in 0.

GotchaShort form
Scopes are not the permission modelThe principal behind the token decides what data is reachable
No refresh tokens for JWT bearer or client credentialsRequest a new access token when it expires
Scopes cannot be requested on those token callsThey come from the app and its permitted-user policy
Username-password flowBlocked by default for orgs created Summer '23 or later, and unsupported by external client apps
Local external client appsNot copied to new or refreshed sandboxes
Client credentials secretAnyone holding the key and secret gets a token; rotate it
Connected apps without ownersNo accountable revoke and rotation path during incidents

Output Artifacts

ArtifactDescription
OAuth decision tableRecommended flow, principal, and policy model
Connected-app reviewFindings on scopes, secrets, policies, and weak legacy choices
Token operations checklistRotation, revocation, and outage-handling actions

Package files