SfSkills Domains Docs GitHub

Home / admin / integration-admin-connected-apps

integration-admin-connected-apps

Use when managing Connected Apps for integration purposes — configuring OAuth policies, IP restrictions, refresh token expiry, pre-authorization assignment via profile or permission set, and monitoring connected app usage via EventLogFile.

Open the skill folder on GitHub


Integration Admin: Connected Apps

This skill activates when an admin needs to configure or troubleshoot Connected App OAuth policies for integration use cases — setting Permitted Users mode, IP Relaxation policy, Refresh Token Policy, and monitoring usage via EventLogFile. It covers the critical post-configuration step that admins most commonly miss: assigning the connected app to a profile or permission set when using pre-authorization mode.


Before Starting

Gather this context before working on anything in this domain:


Questions to Ask Before Configuring

Ask these before opening the app's Manage page. Each answer decides a policy value or an operational step that no error message will later name for you — the app authenticates or it does not, and the platform does not explain which control said no.

AskWhy it mattersWhat a good answer adds
"Which permission set pre-authorizes this app, and is that assignment dated?"isAdminApproved with no permissionSetName / profileName authorizes nobody, and PermissionSetAssignment.ExpirationDate un-authorizes the integration user on a day nobody diarisedA named permission set plus a check that the integration user's assignment has no expiry
"Can the caller enumerate its egress IPs, and who owns the org's trusted-IP list?"ENFORCE is only as strict as that list, and redeploying NetworkAccess replaces the whole list rather than merging into itENFORCE plus a real range list, or a written reason for a looser value
"How does this integration get cut off in an incident — what is the exact step?"OauthToken supports only describeSObjects() and query(); there is no DML delete, so the revoke path is the DeleteToken value against the revoke endpointA runbook line someone has actually executed once, not "revoke the token"
"Who holds the consumer key and secret, and what does rotation cost?"consumerKey can be set only at creation and can't be edited afterwards; only an External Client App has shouldRotateConsumerKey / shouldRotateConsumerSecret, and those need the ignore-warnings deploy attributeA rotation plan that is either an ECA deploy or a replacement app plus a caller cutover
"Does anyone hold Customize Application to run the token inventory?"Without it, OauthToken returns only the caller's own tokens, so a least-privileged reviewer reports "nobody uses this app" about an app in daily useA named reviewer who can actually see org-wide tokens
"Which named user owns this app, and when was it last reviewed?"SetupAuditTrail keeps Setup changes for "at least the last 180 days" — a policy change made two quarters ago has no evidence leftAn owner and a review cadence short enough that the audit trail still covers the gap
"Is the org's enableAdminApprovedAppsOnly switch on?"It changes whether any unapproved connected app can call the API org-wide, and turning it on requires a Salesforce Customer Support request to enable API Access ControlThe blast radius of every per-app policy decision below it

What a proper configuration adds over just setting the three OAuth policies: the app is pre-authorized to a named permission set whose assignment does not expire, the revoke and rotate steps have been run once against a sandbox, the token inventory runs as someone who can see all tokens, and each quarter's review is written down while SetupAuditTrail can still corroborate it.


Core Concepts

Three OAuth Policy Controls

Connected App OAuth policies have three independent controls accessible in Setup > App Manager > [App] > Manage:

  1. Permitted Users: Controls who can authorize the connected app.
    • "All users may self-authorize" — any user can grant access to the app via OAuth consent.
    • "Admin approved users are pre-authorized" — only users whose Profile or Permission Set has the connected app explicitly assigned can authenticate. No consent screen is shown — authentication is immediate if the user is assigned.
  2. IP Relaxation: Controls how the org's login IP restrictions interact with connected app sessions.
    • "Enforce login IP restrictions" — IP restrictions from the user's profile apply to API calls via this connected app.
    • "Relax IP restrictions" — API calls via this connected app bypass the user's profile IP restrictions entirely.
    • "Relax IP restrictions, with second factor for non-login IPs" — Relaxes IP for authenticated sessions but requires MFA for logins from outside the profile's IP range.
  3. Refresh Token Policy: Controls how long a refresh token remains valid.
    • "Immediately expire refresh token" — Tokens expire immediately, requiring re-authentication every API call. Suitable for server-to-server flows that do not use refresh tokens.
    • "Expire refresh token if not used for N days" — Inactivity-based expiry.
    • "Expire refresh token after N days" — Absolute time-based expiry.
    • "Immediately expire refresh token if IP address changes" — Security control for sensitive contexts.

Pre-Authorization Mode Assignment

When "Admin approved users are pre-authorized" is selected, the connected app must be assigned to one or more Profiles or Permission Sets. This assignment is done via:

Without this assignment, the "pre-authorized" setting effectively blocks all users.

Connected App Usage Monitoring (EventLogFile)

Two EventLogFile event types capture connected app activity:

Both require the Event Monitoring add-on. Access via REST API:

GET /services/data/vXX.0/query?q=SELECT+Id+FROM+EventLogFile+WHERE+EventType='ConnectedApp'+AND+LogDate=TODAY

The standard Setup UI Login History shows connected app sessions but does not capture OAuth token-level events.

Monitoring Without the Add-On: Four Standard Objects

Every org has these three, add-on or not. They answer different questions and each carries a constraint that silently corrupts the answer if you don't know it.

ObjectAnswersConstraint the Object Reference states
ConnectedApplicationWhat policy actually landed on each app"all fields are read-only"; supports describeSObjects(), query(), retrieve()
OauthTokenWho currently holds a grant, and when they last used it"Users with the Customize Application permission see all tokens for all users in the org. Otherwise, you see only your own tokens." query() returns 500 rows, queryMore() up to 2,500 total, and "No more records are returned after 2,500"
LoginHistoryWhich sessions the app produced, from whereOnly twelve fields are filterable — Application, SourceIp and Status are not among them
SetupAuditTrailWho changed a policy, and whenHolds Setup changes "for at least the last 180 days"; SELECT count() works but SELECT count(Id) fails

LoginType is filterable, and the values that mean connected app are Application, Oauth, Remote Access Client and Oauth2, Remote Access 2.0 — two of the three contain a comma inside the picklist value itself.

What the app is consuming. A connected app's traffic lands in the org's shared 24-hour inbound API allocation, which the Salesforce Developer Limits and Allocations Quick Reference sets as 15,000 calls for Developer Edition and, for Enterprise and Professional with API access, "100,000 + (number of licenses x calls per license type) + purchased API Call Add-Ons" — 1,000 per Salesforce or Salesforce Platform licence, rising to 5,000 each on Unlimited and Performance Edition. A Full Sandbox not created from a template gets 5,000,000. Adding an integration adds load to that one bucket, so the review should record call volume alongside token count. The same reference caps stored credentials: "Salesforce stores third-party access and refresh tokens of up to 10,000 characters in length."

Revocation, Rotation, and the Periodic Review

These three are the operations that keep an app safe after it exists. None of them is a Setup checkbox, and each has a shape the platform does not advertise.

OperationThe actual mechanismWhere it bites
Revoke one grantOauthToken.DeleteToken posted to the revoke endpoint: https://MyDomainName.my.salesforce.com/services/oauth2/revoke?token=(the Delete Token)OauthToken supports only describeSObjects() and query() — there is no DML delete to write a Flow or Apex around
Kill an app entirelyBlock on the Connected Apps OAuth Usage page, or sessionPolicy/policyAction = Block, which "ends all current user sessions with the connected app and prevents all new sessions"Blocking is org-wide and immediate; it is not a per-user action
Rotate the key or secretOn an External Client App, shouldRotateConsumerKey / shouldRotateConsumerSecret — "if this field is set to true, you must include the ignore warnings attribute in the deploy command"A ConnectedApp has no such field: consumerKey "can be set only during creation" and after save "it can't be edited"
Periodic reviewA written per-app row: owner, last-reviewed date, and the date the token-count query was actually runSetupAuditTrail only reaches back 180 days, so a review cadence longer than two quarters cannot be corroborated

The deployable file that carries these policies — the full connectedApp-meta.xml, the External Client App four-file set, and the Named Credential pair — belongs to admin/connected-apps-and-auth. This skill shows only the policy excerpts you edit during operations; see references/metadata-examples.md.


Common Patterns

Configuring a Server-to-Server Integration App

When to use: Setting up a connected app for a server-to-server integration (middleware, ETL, MuleSoft) where no user consent flow is needed.

How it works:

  1. Create the connected app in Setup > App Manager > New Connected App.
  2. Enable OAuth, add required scopes (api, refresh_token, offline_access).
  3. Set Permitted Users to "Admin approved users are pre-authorized."
  4. Assign the connected app to the integration user's Profile: Profile > Connected App Access > enable the app.
  5. Set Refresh Token Policy based on the integration's session management: for JWT bearer flow (no refresh tokens), set "Immediately expire refresh token."
  6. Set IP Relaxation to "Enforce login IP restrictions" — the integration server's IP should be added to the integration user's profile trusted IP ranges.

Why this matters: Without step 4, no user can authenticate against the connected app, even the admin. The most common support issue after creating a pre-authorized connected app.

Monitoring Connected App Usage After an Incident

When to use: An integration is failing and you need to determine which users are authenticating, from what IPs, and when token refreshes are occurring.

How it works:

  1. Query EventLogFile for the ConnectedAppOAuth event type for the relevant date range.
  2. Parse the CSV log file (EventLogFile stores log data as a downloadable CSV).
  3. Filter by the connected app's client_id and the integration user's username.
  4. Review the GrantType, IP address, and TokenType columns to identify anomalies.

Decision Guidance

SituationRecommended ApproachReason
Server-to-server integration (no user consent)Admin approved users are pre-authorized + profile assignmentPre-authorization prevents consent screens; profile assignment restricts to integration user
Users need to authorize app themselves (OAuth)All users may self-authorizeAllows individual user consent flow
Connected app blocking all authentication after "pre-authorized" setCheck profile or permission set assignmentMissing assignment is the most common cause
Integration failures after IP changes at integration serverReview IP Relaxation settingEnforce login IP blocks new IPs; Relax if integration server IPs change frequently
Refresh token expired causing integration failureAdjust Refresh Token PolicyIncrease expiry window or use JWT bearer flow (no refresh tokens)
Monitor which users are hitting a connected appEventLogFile ConnectedApp and ConnectedAppOAuth event typesStandard UI does not show OAuth token-level detail
Uninstalled app blocking usersAudit Connected Apps OAuth Usage in Setup, re-permit the appSeptember 2025 policy: uninstalled apps blocked by default

  1. Answer the seven questions above and fill the template. templates/integration-admin-connected-apps-template.md captures the app name, integration user, the three policy values, the pre-authorizing permission set, and the IP ranges. If the app does not exist yet, stop here and go to admin/connected-apps-and-auth — this skill starts once there is an app to operate.
  2. Write the policy excerpt from references/metadata-examples.md. Copy the hardened oauthPolicy block (ipRelaxation ENFORCE, an explicit refreshTokenPolicy, isAdminApproved plus permissionSetName) into the existing connectedApp-meta.xml. Do not author the whole file here; the sibling owns it.
  3. Pair the permission set to the integration user. Deploy the pre-authorization permission set fragment, then create the PermissionSetAssignment with ExpirationDate left null. Confirm with the pairing SOQL in references/metadata-examples.md.
  4. Run python3 scripts/check_integration_admin_connected_apps.py --manifest-dir force-app/main/default. Fix every ERROR — ipRelaxation BYPASS, isAdminApproved with no grantee — before deploying. Justify each WARN (infinite refresh policy on an admin-approved app, Full scope, a client-credentials user) in the template's Notes section.
  5. Deploy, then verify in the org. sf project deploy start -x manifest/package.xml --dry-run, then without the flag. Run the ConnectedApplication and OauthToken verification queries from references/metadata-examples.md as a user holding Customize Application — a least-privileged reviewer sees only their own tokens and will report a false clean.
  6. Rehearse revoke and rotate once, in a sandbox. Revoke one grant via DeleteToken against the revoke endpoint, re-authorize, and confirm the integration recovers. For rotation, decide now whether the path is an ECA deploy with the ignore-warnings attribute or a replacement app plus a caller cutover — the connected app's consumerKey cannot be edited after save.
  7. Commit the review checklist and schedule it. Fill templates/connected-app-review-checklist.yaml with one row per app (owner, last-reviewed, token-count-query-run) and re-run the checker with --manifest-dir pointed at the folder holding it; the checker lints those three fields. Set the cadence inside 180 days so SetupAuditTrail still corroborates the previous review.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. Pre-authorized mode requires explicit profile/permission set assignment — Setting "Admin approved users are pre-authorized" without assigning the connected app to any Profile or Permission Set blocks ALL users from authenticating, including the admin who created the app. The authentication attempt returns a generic OAuth error. The fix is straightforward — assign the app to the relevant profile or permission set — but the error message does not indicate the missing assignment.
  2. Uninstalled connected apps are blocked by default (September 2025) — As of September 2025, Salesforce changed the default behavior so that uninstalled connected apps are blocked for most users. Any app that was uninstalled but whose tokens are still in use by integrations will fail silently. Admins must audit connected app usage in Setup > Apps > Connected Apps > OAuth Usage and explicitly permit any still-active apps.
  3. ConnectedApp EventLogFile events require Event Monitoring add-on — ConnectedApp and ConnectedAppOAuth event types are NOT available in the standard Login History or audit trail UI. They require the Event Monitoring add-on and must be queried via the REST API on the EventLogFile object. Admins without this add-on have no visibility into OAuth token-level activity.

Output Artifacts

ArtifactDescription
OAuth policy configurationPermitted Users, IP Relaxation, Refresh Token settings for the connected app
Profile/permission set assignmentStep-by-step for assigning connected app to integration user's access
EventLogFile queryREST API query template for monitoring connected app usage
Connected app security checklistAudit template for connected app security posture review

Reference Files

FileRead it when
references/metadata-examples.mdYou are editing the policy block on a live app, writing the pre-authorization permission set, or need the monitoring SOQL, the revoke procedure, the rotation deploy, or the review-checklist YAML shape
references/gotchas.mdSomething changed and the integration broke, or a monitoring query returned an answer you don't trust — truncated OauthToken results, an unfilterable LoginHistory field, an assignment that expired, a rotation deploy that was rejected
references/examples.mdYou want the worked end-to-end narratives: pre-authorized mode blocking everyone, and an incident traced through token-level events
references/well-architected.mdYou need the Security / Operational Excellence framing for a review, or the exact official source behind a claim in this skill
references/llm-anti-patterns.mdYou are checking AI-generated connected-app operations guidance before acting on it
templates/integration-admin-connected-apps-template.mdBefore configuring or auditing one app, to capture the policy values, integration user, IP ranges and monitoring plan in one place
templates/connected-app-review-checklist.yamlAt each periodic review — one row per app, linted by the skill checker
scripts/check_integration_admin_connected_apps.pyAfter editing policy XML and before deploying, and again after updating the review checklist

Package files