OAuth Scope Minimization Across Third-Party API Integrations
Narrow OAuth scopes before a breach turns one stolen token into a company-wide disaster.
OAuth scope minimization comes down to one question: how much damage can a single stolen or forgotten token do? The scope string attached to that token is the answer. Get the scope wrong at setup, and you've already decided how bad your worst day gets, months or years before it happens.
Why over-scoping is the path of least resistance and how it compounds over time
Ask any developer why an app requests full Drive access instead of read-only, and the honest answer is usually some version of "so we don't have to ask again." That's not laziness, exactly. It's incentive design working exactly as built.
Under-scope an integration and it breaks. Someone in sales can't sync a calendar event, they file a ticket, and now there's a fire drill with your name on it. Over-scope the same integration and, if it works, nobody says a word. Silence is the reward for asking for too much. Nobody gets promoted for narrowing a scope down, and nobody gets blamed for granting one that's too wide. That's not an accident. It's a structural gap in accountability, and it shows up the same way across every department:
- Marketing hands an analytics tool full Drive access when read-only would cover the entire job.
- Sales lets a CRM integration take complete calendar control, when all it ever needed was permission to create events.
- Finance approves an expense app with admin rights, when submitting expenses needs almost nothing at all.
And the person clicking "Allow" on the consent screen rarely reads it. The screen presents itself as a formality, a box to check on the way to using the tool, not a real decision point with real consequences. Security research has found that close to one in five websites, 18.53% by one count, request more OAuth permission than they actually need. That's not a fringe problem. That's a meaningful chunk of the entire integration ecosystem running wider open than it should.
Here's the part that makes it worse over time: scopes don't expire on their own. A "full access" grant from three years ago doesn't care that the password's been reset since, or that MFA got turned on, or that the person who approved it left the company last spring. It just sits there, quietly working.
Obsidian Security has documented exactly this pattern with something they call "Campaign Analytics Pro": This pattern plays out across enterprises on a near-daily basis: a tool gets broad access, the person who approved it moves on, and the grant just sits there. And yet the access persisted, Most organizations couldn't tell you if it's happening to them right now, because they don't have a list of which scopes they've approved in the first place.
What compromised and orphaned tokens actually cost when blast radius goes uncontrolled
The numbers back up the anecdote. SaaS breaches jumped 300% in 2024, according to Obsidian Security, with 28% of organizations reporting a cloud or SaaS-related breach, and more than a third of those getting hit more than once in the same stretch. That's not one bad month for one unlucky company. That's a pattern.
Third parties are doing more of the damage every year, too. IBM's 2025 Cost of a Data Breach Report found third-party involvement in 15% of breaches in 2024. In 2025, that number doubled to 30%. When a partner's OAuth token gets compromised, it's not their blast radius anymore. It's yours.
The Salesloft-Drift breach from August 2025 is the clearest example on record. Attackers compromised Salesloft Drift credentials, then used those to grab connection secrets feeding into downstream SaaS applications. From there, they rode OAuth tokens straight into customer Salesforce instances, more than 700 companies deep, according to Microsoft Threat Intelligence. Obsidian Security put the blast radius at ten times larger than incidents where attackers breach Salesforce directly. Ten times. That multiplier reflects something other than how skilled the attackers were. It's about how many doors a single trusted integration leaves unlocked.
It didn't stop there. A follow-up campaign in November 2025 went after Gainsight-published apps connected to Salesforce, using those same trusted external connections to keep API access alive across roughly 200 organizations. Different vendor, same playbook: find the integration everyone trusts, and ride it in.
Microsoft had its own version of this in 2024. Russian state-backed attackers used a basic password spray against a legacy, non-production test account, nothing fancy, and from there found a legacy OAuth app sitting around with high-level permissions nobody had bothered to rein in. That app gave them access to corporate email. The break-in was cheap. The permission level is what made it expensive.
Then there's UNC6395, tied to that same Salesloft Drift chatbot integration, where compromised OAuth tokens let attackers exfiltrate data from Salesforce instances across more than 700 organizations. Google's own read on the incident was blunt: the access looked legitimate because the tokens were legitimate. Nothing to detect as anomalous, because from the system's point of view, nothing was wrong. On August 20, 2025, the vendor and Salesforce revoked every active token tied to that integration, and here's the detail that ought to worry every security team reading this: revocation happened at the integration level, not scoped down to just the breached customers. Every single customer using that integration lost their connection, whether their data was touched or not.
The financial fallout from this kind of failure isn't abstract, either. Jaguar Land Rover's manufacturing shutdown carried an estimated £1.9 billion hit to the UK economy. The Marks & Spencer ransomware incident cost roughly £300 million in lost operating profit. Both trace back to identity-perimeter and supply-chain breach patterns, per research published on ResearchGate. IBM's 2025 report puts the average global breach cost at $4.44 million (down slightly from $4.88 million the year before), with US breaches averaging $10.22 million, and breaches involving stolen credentials landing around $4.50 million. Scoped-token abuse sits squarely inside that band.
Strip away the vendor names and the dollar figures, and the pattern underneath is almost boring in its consistency: attackers didn't crack encryption. They didn't slip past MFA through some clever trick. They just used tokens that were already sitting there, already trusted, already carrying more permission than the job called for.
Mapping every third-party integration to the minimum scope each endpoint actually requires
The fix starts with a boring but essential exercise: list every endpoint your application touches, then write down the minimum scope each one actually needs. Not a policy memo. A ledger, endpoint by endpoint.
Google's own OAuth guidance recommends requesting scopes as narrowly as the feature requires. An app that needs Calendar access for one specific feature should limit its request to just that scope, not bundle it together with everything else upfront. GitHub frames the same principle from the developer side: an OAuth app should request only what its intended functionality actually requires, because if the token ever gets compromised, the damage is capped at whatever was requested in the first place.
Scope naming matters here more than it sounds like it should. A scope like users.read or transactions.create tells you, at a glance, exactly what it does: a resource and an action, spelled out. Compare that to something vague like admin or full_access or just data, terms that can't really be audited because nobody agreed on where their edges are. Vague scopes hide risk. Precise ones expose it, which is the entire point.
For more complex systems, a hierarchical, colon-separated structure holds up well in practice, per guidance from Curity: order versus order:payment versus order:shipping:address, each level narrowing the grant further down. Default to read-only, and only add a :write suffix when there's an actual justified need for it, the way inventory differs from inventory:write. That said, don't go overboard carving out scopes preemptively. Add granularity when a real business need shows up, not because it seems thorough. Too many fine-grained scopes turns into its own maintenance headache, one nobody can keep straight six months later.
A few other things worth building into the process:
- Don't assume a third-party API's "read" scope is harmless just because it's labeled that way. It might expose metadata far more sensitive than the name suggests. Read the documentation before authorizing, every time.
- In multi-tenant systems, enforce tenant isolation at the scope level, not just in application code. Code-level boundaries can be bypassed. A boundary baked into the scope itself is a lot harder to route around.
- Where it's an option, use scopes that expire automatically instead of holding a broad grant indefinitely. Shorter windows mean less time for a stolen token to do anything useful.
For advanced setups, DPoP (Demonstrating Proof of Possession) binds a token cryptographically to a specific client key pair, so an intercepted token is useless without the private key that goes with it. Google recommends it for public clients and high-sensitivity APIs, and it works alongside PKCE rather than replacing it. In microservice architectures, token exchange lets one service request a narrow-scope token for a specific downstream call instead of passing a broad, all-purpose token across every service boundary in the chain.
Governing what persists: the audit, revocation, and lifecycle controls that prevent orphaned-scope accumulation
Getting the scope right at authorization time solves exactly half the problem. The other half is what happens after, and that's where "Campaign Analytics Pro" comes back into the picture: that wasn't a bad authorization decision. It was a governance failure, three years of nobody checking back in.
The floor here is a living inventory: a running, current record of every OAuth token in the environment, which app holds it, which scopes it carries, which user or service account approved it, and when. Most SaaS platforms expose dashboards or APIs that can generate this. Dedicated SaaS security tools, per AppOmni, offer centralized monitoring and alerting on top of that so nobody has to check by hand.
Google automatically deletes OAuth clients after six months of inactivity, and that's genuinely useful, but treat it as a backstop, not a strategy. Google's own best-practices guidance recommends removing unused clients proactively, well before that six-month clock runs out. Waiting for the automatic deletion means leaving an open door unattended for however long it takes the timer to run.
Here's a gap that catches teams off guard: removing an OAuth app may not be sufficient on its own to terminate all active tokens, and teams should verify that revocation is fully enforced. Security teams need to check, integration by integration, whether that enforcement is actually happening. Prioritize the audit around integrations carrying the broadest permissions, since those carry the greatest blast radius if left unchecked.
The UNC6395 incident is the clearest lesson on what happens when revocation gets messy. The UNC6395 incident showed that when a breach runs through a shared integration, the revocation swept across all connected customers, not just those confirmed to be affected. Companies that never bothered to inventory their integrations were the last to find out and the slowest to get back online.
A workable audit rhythm looks something like this:
- Map every user and service account that's consented to each connected app.
- Flag scopes that are authorized but never actually used, behavioral detection can catch apps sitting on permissions they never touch.
- Strip out the unused scopes, and rotate credentials on a set schedule.
- Watch token usage for anything off, access outside normal patterns, or access continuing after someone's left the company.
- Build scope validation into CI/CD, so deployed integrations get checked against an approved list before they ever reach production.
None of this works without solid refresh token policy underneath it: short-lived access tokens, tight controls on refresh tokens, and a revocation process that can move the instant a compromise signal shows up. These aren't nice-to-haves bolted on for compliance. They're the mechanism that makes scope minimization actually stick instead of decaying the moment nobody's watching.
One more wrinkle worth naming: individual scopes can look perfectly safe sitting alone, and still add up to something dangerous once combined. Read access from one app, write access from another, admin from a third, stacked across a handful of connected tools, and suddenly there's a path for lateral movement that no single grant would have allowed on its own. Inventory needs to track combinations across the whole stack, not just each grant in isolation.
What a defensible integration posture looks like in practice across a SaaS stack
None of this is a one-time project with a finish line. It's a loop: authorize minimally, keep the inventory current, revoke fast when something looks wrong, validate every deployment against what's actually approved. Skip a step and the loop breaks down.
Across the 2024 and 2025 incidents Microsoft and others have documented, a pattern keeps repeating: attackers stopped bothering with passwords and MFA and went straight for the authorization layer instead, the tokens and the consent decisions behind them. The point of failure moved. It used to be the credential. Now it's the consent screen and everything that token is allowed to do afterward. A defensible posture treats every OAuth grant as an ongoing security decision that needs revisiting, not a box checked once at setup and forgotten.
Risk doesn't spread evenly across a SaaS stack, either. Some categories carry more of it than others:
- Marketing and analytics tools tend to carry the widest, least-inventoried scopes in most organizations, often approved by an individual contributor rather than anyone in IT, and they're the ones least likely to show up in continuity planning when something goes wrong.
- CRM and revenue tools routinely hold write access across calendar, email, and contact data, which makes them high-value targets: one trusted vendor relationship, wired into several systems at once.
- Finance and HR tools tend to get admin-level grants at setup that nobody revisits, and once the employee who approved it moves on, that's the textbook setup for an orphaned token.
Behavioral monitoring closes the loop that inventory alone can't. Knowing what an app is allowed to do only gets you halfway. Knowing what it actually does with that permission is the other half. An app sitting on full drive access that only ever calls drive.readonly endpoints is over-scoped, plain and simple, and it should get reauthorized down to the narrower grant it's actually using.
All of this sits on top of a standards floor that's shifted meaningfully in the last year. RFC 9700, published in January 2025, is now the IETF's Best Current Practice for OAuth 2.0 security, and it strongly supports PKCE for authorization code flows while strongly discouraging the Implicit flow and the Password grant. A 2025 draft update builds on it further, extending the same security guidance to threats that surfaced after the original RFC went out. The standard sets the baseline. It doesn't enforce a thing. Which scopes get requested, and how long they're allowed to sit there unused, is still entirely on whoever built the integration, and whoever forgot to check on it three years later.



