Connected Apps are the most overlooked attack surface in Salesforce security audits. They inherit the permissions of any user who authorizes them, and they keep working long after that user leaves the company, changes roles, or forgets they ever clicked "Allow."
A Connected App installed by a contractor in 2022 may still have an active refresh token for your CEO's account in 2026. Orgs routinely accumulate 30, 40, 60 of these apps — most with stale tokens, broad OAuth scopes, and no admin who can say what they're for. Every one is a sitting credential.
This guide covers how to find every Connected App in your org, identify which ones are actually still in use, audit the permissions they operate under, and revoke the ones that aren't worth keeping. It ends with a recurring review process so this never falls behind again.
What a Salesforce Connected App Actually Is
Connected Apps are the Salesforce implementation of OAuth 2.0. They let external services (data warehouses, marketing platforms, internal integrations, third-party tools) authenticate to your org without storing a username and password. The integration runs in the security context of an authorized user — which is the foundation of both their usefulness and their risk.
Two distinct kinds of Connected App exist in your org:
- Created Connected Apps — registered in your org for a specific integration. You control the OAuth scopes, the Permitted Users policy, and the callback URL. Examples: your internal data warehouse connector, your Snowflake sync, your custom middleware.
- Installed Connected Apps — created by Salesforce or third parties and installed by users who authorized them. Includes Salesforce-built apps (Workbench, Salesforce mobile), AppExchange packages, and external SaaS tools (Marketo, Zapier, Workato, Heroku Connect).
Both kinds can hold refresh tokens against user accounts. Both need to be in your audit. But the failure modes are very different — a stale first-party integration can break a critical pipeline, while a stale third-party app is mostly a security risk. You audit them with the same process but treat them differently when you revoke.
The OAuth scope is the real permission boundary
Users see a list of scopes when they authorize an app — "Access and manage your data," "Perform requests on your behalf at any time," "Access your basic information." Most users accept them all without reading. The scopes are what the app can do, regardless of the user's profile or permission sets.
An app with the api and refresh_token scopes inherits every permission the authorizing user has. An app with full scope (which Salesforce recommends against but still allows for legacy integrations) can read and write any record the user can see, including those the user can only see because of a permission set grant or sharing rule.
The OAuth Audit Framework: Four Phases
A Connected App audit has four phases. Run them in order — each one grounds the next with information you didn't have before you started.
Phase 1: Inventory — What apps exist and what is each one for?
Setup → App Manager shows every Connected App in your org. Most admins have never opened it. Open it now and export the full list. Capture:
- App name — what is it called in the UI?
- Created by — a user name, a Salesforce package install, or a third-party provider?
- Created date and last modified date — when did it first appear, and when was its policy last reviewed?
- OAuth scopes —
api,refresh_token,full,offline_access,custom_scope— whatever the app requested. - Permitted Users policy — "All users may self-authorize," "Admin approved users are pre-authorized," or "Admin approved users are pre-authorized for specific permission sets."
- Callback URL — where OAuth tokens are sent.
Most orgs surface surprises here. Apps installed for a 2022 pilot that never got cleaned up. Apps with no owner. Apps with callback URLs pointing at domains that no longer resolve. Apps with full scope that nobody can explain.
Phase 2: Token Inventory — Who authorized what, and are the tokens still live?
An app with no authorized users is harmless. An app with active refresh tokens is the actual risk surface. Shift from inventory to token analysis.
Setup → OAuth Usage (or Manage OAuth Policies and Connected Apps) shows the authorized users per app. For each one:
- Is the authorizing user still an Active employee? ⚡ critical
- If Active, has the user logged in within the last 90 days?
- Has the app made an API call on behalf of this user within the last 90 days?
- Has the user changed roles since they authorized the app?
- Is the user's Manager or HR record consistent with needing this app?
- Cross-reference against your offboarding checklist — was the user's access revoked but the OAuth token was missed?
- For service accounts: is the service account still active, and is the use case for the integration still valid?
The pattern you find is familiar: apps authorized by former employees whose user records were deactivated but whose OAuth sessions are still flagged as Active. The deactivation stops new logins but doesn't invalidate existing refresh tokens by default — those tokens are still good until explicitly revoked or until the org-wide refresh-token policy rotates them.
Phase 3: Policy Audit — Is each app configured the way it should be?
Apps accumulate scope creep the same way permission sets do. A first-party integration that started with api scope got refresh_token added "just in case" by an admin trying to debug an issue in 2023, and neither of them was removed. Audit the policy of each app against its actual use.
- Refresh token policy — is "Refresh token is valid until revoked" set, or is there a rotation policy? Unbounded refresh tokens are the high-risk setting.
- Permitted Users — apps with "All users may self-authorize" can be silently authorized by anyone who clicks through the OAuth prompt. Switch these to "Admin approved users are pre-authorized for specific permission sets" unless self-authorization is genuinely required.
- IP restrictions — apps that should only run from a specific range (your data warehouse's egress IPs, your middleware servers) should have IP restrictions enforced.
- Session policy — confirm timeout and lock-to-domain settings are aligned with the rest of your org policy.
- Run As — verify the app's "Run As" user (if a server-to-server flow) is a dedicated service account, not a personal user with high permissions.
Anyone who can explain why an app has the policy it has, in writing, gets to keep it. Anyone who can't — the app is on a watch list.
Phase 4: Revocation Planning — Which apps can be safely removed?
Revocation is the moment of truth. You know what's there, who authorized it, what scope it has. Now you decide who stays and who goes. The decision is not the same for every app.
For each app, classify into one of three buckets:
- Critical — keep, but tighten. An active integration your business depends on. Document the owner, the use case, the fallback, and the deprecation plan. Audit quarterly.
- Useful but stale — reauthorize or remove. An app that probably has a real use case but hasn't been touched in 6+ months. Reach out to the apparent owner. If they confirm it's still needed, set a calendar reminder to re-audit and require them to document the integration scope. If they don't respond, revoke.
- Unknown or unused — revoke. An app nobody can explain, an app with no recent API activity, an app installed by a user no longer with the company. Revoke the tokens first, then block the app. Watch for breakage for one billing cycle, then remove the Connected App entry.
For bucket 3 — and only bucket 3 — run the revocation playbook below. For bucket 2, talk to people first. For bucket 1, the goal is tightening, not removal.
Run the Permission + Connected App Audit Together
Cross-reference Connected Apps, refresh token holders, and permission set assignments in a single audit. No Salesforce credentials required to start.
The Connected App Revocation Playbook
Revoking a Connected App's tokens in production can break things. Plan it like a deployment: announce, schedule, execute, verify.
- Send a heads-up — to whoever installed the app, their manager, and the team that owns the downstream integration. "We are revoking tokens for [App Name] on [Date]. Please re-authorize after that date if still needed." Two weeks' notice is a reasonable floor.
- Revoke all current tokens — for the chosen app. Setup → App Manager → Manage App Policies → "Revoke all tokens." This terminates existing sessions immediately. Anything depending on the app will start failing on the next API call.
- Block the app — change the Permitted Users policy from "All users" to "Admin approved" with zero permission sets selected, OR revoke the OAuth consumer key. Either blocks new authorizations.
- Watch for breakage — monitor Setup Audit Trail and your own application error logs for 48–72 hours. Have an owner on-call who can re-authorize if a missed critical integration starts failing.
- Delete or archive — if no one has come forward, delete the Connected App. If a manager has confirmed it's needed, archive the entry with a clear "DELETED — re-add with policy [X]" note for future admins.
The risks are asymmetric. The cost of leaving a stale app with active tokens is higher than the cost of temporarily breaking one non-critical integration and putting it back. Err toward revocation and rebuild.
The Cascading Risk: Agentforce and AI Agents
As of 2026, AI agents and Agentforce tools sit on top of the same OAuth plumbing. An AI agent acting on behalf of a user inherits that user's Connected App tokens. If that user has authorized an over-permissioned app from 2022, the agent's actions run under those scopes — and the agent may make API calls the user would never have made manually.
AI agents don't fire the same alarms humans do
A human user making an unexpected API call leaves a clear trail in Setup Audit Trail. An agent making the same call is harder to attribute. It may invoke flows, modify records, or trigger external integrations, all on behalf of an OAuth token that was authorized years ago by a user who is no longer in the org.
The good news: cleaning up Connected Apps before turning on Agentforce prevents the worst-case scenarios. The bad news: most orgs enable Agentforce without an audit pass. Run the OAuth audit before any AI agent rollout, not after.
Two specific risks to flag for any AI roll-out:
- Stale token ancestor. An agent works under the OAuth context of a user with a stale 2022 token chain. Audit the user's authorized apps before the agent goes live.
- Inherited scope creep. An agent is given the same OAuth scopes as a power-user account. If the power user has granted
fullto a Connected App from 2021, the agent inherits that scope by default.
Both of these are about tightening the user → app → agent trust chain before the agent has the chance to act on it. The Connected App audit is the prerequisite work, not the wrap-up.
Building the Recurring Review
A one-time audit is a snapshot. A quarterly review is a posture. The review doesn't have to be heavy — 90 minutes every quarter, with two people (an admin and a security lead) walking the inventory list and signing off.
What to review each cycle:
- New Connected Apps installed since last cycle — review and approve
- Authorization events on high-scope apps — any unexpected user accepting?
- Connected Apps with no API activity in the last 90 days — flag and reach out
- Apps with
fullscope still in place — confirm a current justification exists - Refresh-token policy still set to "valid until revoked" for any app — confirm or change
- Apps installed by users who left the org — identify and revoke
- Apps requesting new OAuth scopes since last cycle — review and approve
- Integration with org-wide flows — does any Connected App trigger Flows that could be exploited?
A standing 90-minute calendar item, the right two people, and a checklist that's faster to run than to ignore. That's what a recurring Connected App review looks like.
How to Find Your Connections Starting Today
If you're starting from zero, here's the shortest possible path. Don't try to do it exhaustively on day one. Get the inventory and the obvious slam-dunks.
- Open Setup → App Manager. Count the entries. That number is your starting point.
- For each app marked as installed by a specific user, check whether that user is still Active. If not, the app is at high risk.
- Open Setup → OAuth Usage. Sort by last-used date. Anything older than 180 days is a candidate for revocation after a heads-up.
- For each app with
fullscope, ask the owner — if no owner exists, the app is a Problem. - Document the keep-list with one line per app: name, owner, use case, last reviewed date.
- Revoke three obvious slam-dunk stale apps this week. The easiest ones, to get the cadence going.
- Set the recurring quarterly review on the calendar.
The first pass is slow. The second is faster. By the third, the review has a rhythm, and the org stops accumulating dead OAuth sessions.