The OAuth Permission That Could Compromise Your Entire Org
- Martin Snyder
- Aug 19, 2025
- 7 min read

If you’ve ever wondered how a harmless-looking “Sign in with…” button can silently turn into a persistent backdoor, here’s the short version: Waldo Security helps you see and govern every OAuth grant across your SaaS estate, right-size risky permissions, and automatically revoke tokens when people change roles or leave—so a single bad consent doesn’t snowball into a breach. Start by mapping what’s actually connected with Instant SaaS Discovery, then use our framework-aligned evidence in the SaaS Compliance Overview to prove control in audits.
The twist: the scariest permission isn’t the obvious one
When people talk about dangerous OAuth scopes, they usually jump to the usual suspects: Files.ReadWrite.All, Mail.ReadWrite, Directory.ReadWrite.All, or app-only permissions that operate without a user. Those are dangerous, no doubt. But the permission that quietly amplifies almost any other scope is the unassuming one many teams ignore:
offline_access — the “keep access when I’m not around” permission.
In plain English, offline_access tells the identity provider (IdP) to issue a refresh token, which the app can exchange for new access tokens without the user present. That’s normal OAuth behavior; it’s how apps keep working when you close your laptop. It’s also why a one-time consent can become months (or years) of access unless you deliberately revoke it. Microsoft’s documentation spells out that offline_access enables long-lived access via refresh tokens; Google’s docs do the same with access_type=offline. (Microsoft Learn, Google for Developers)
This is the multiplier. Pair offline_access with a broad scope like Files.ReadWrite.All (or its Google Drive equivalent), and you don’t just have wide permissions—you have time. And time is what turns a simple “try this productivity app” into an enduring foothold.
Quick refresher: delegated vs. application permissions
Understanding the playing field helps you prioritize what to fix first.
Delegated (on behalf of a user): The user clicks “Allow,” the app acts as them. These consents are what most people encounter. With offline_access, the app can continue acting as the user when they’re gone. Microsoft’s delegated flows explicitly call out the use of refresh tokens for this purpose. (Microsoft Learn)
Application (app-only): The app acts as itself. These are approved by admins and can be sweeping (e.g., “read and write all files in the tenant”). Microsoft ranks certain permissions by privilege and calls out Directory.AccessAsUser.All (delegated) and Directory.ReadWrite.All (app or delegated) among the most powerful and risk-bearing. (Microsoft Learn)
Both categories can be safe with least privilege and oversight. Both become dangerous when combined with offline_access (for delegated) or when granted too broadly (for app-only).
How a compromise unfolds in the real world
Consent phishing. An attacker hosts a legitimate-looking app and asks a user to “Connect your calendar to get smart scheduling,” requesting a cocktail of scopes including offline_access. Microsoft flags this attack pattern and recommends app-consent policies that limit who can approve what. (Microsoft Learn, TECHCOMMUNITY.MICROSOFT.COM)
One click, long tail. The user authorizes the app. The IdP issues an access token (short-lived) and a refresh token (longer-lived). Even if the access token expires in ~1 hour, the refresh token can silently mint new ones. The OAuth spec and vendor docs are clear: refresh tokens exist to let apps keep working without the user re-authenticating. (IETF Datatracker, OAuth Community Site)
Privilege + persistence. If the app also got a broad scope—say Files.ReadWrite.All or mail send/read/write—the attacker now has durable access to sensitive data and actions. In Graph, these scopes are widely documented and should be used with extreme caution. (Microsoft Learn)
Password changes don’t help. Because the app uses refresh tokens, simply changing the user’s password won’t necessarily shut the door. You have to revoke tokens and remove the consent.
Zombie access after offboarding. If offboarding misses SaaS grants outside your core suite, the token just…keeps working. That’s the “oh no” moment during incident response.
Why offline_access deserves special attention
It converts a moment into a relationship. Without it, an app loses access when the access token expires (minutes to hours). With it, access continues until the refresh token is revoked, rotated, or expires on a long schedule.
It muddles causality. Incidents become harder to timebox because the attacker can come and go quietly, refreshing tokens at will.
It defeats “just reset the password.” Users (and sometimes responders) assume a password reset severs access. With refresh tokens, it doesn’t—unless you revoke consent and tokens.
That’s why this permission is often the difference between a noisy, short-lived incident and a quiet, costly one.
“Okay, so what do we do about it?”
Here’s a practical, human-friendly plan that gets results fast without grinding your teams to a halt.
1) Inventory grants you actually have (not the ones on a slide)
Pull a complete list of OAuth grants across your major identity systems and suites (Microsoft 365, Google Workspace, Slack, GitHub, Atlassian, etc.). For each grant: who authorized it, when, which scopes (including offline_access), whether the publisher is verified, and the last time it was used. Microsoft publishes guidance and even scripts for detecting illicit consent grants—use them if you’re rolling your own. (Microsoft Learn)
With Waldo: Our discovery and OAuth governance pulls grants from the major suites into one view, flags broad scopes, highlights offline_access, and surfaces risky publishers. You’ll know who consented to what—fast.
2) Triage by “blast radius × persistence”
Give each grant a simple score:
Blast radius: Data sensitivity + action breadth. (Files.ReadWrite.All or anything *.ReadWrite.All? Admin APIs? Directory operations?)
Persistence: Presence of offline_access, token age, and whether the app is actively used.
Trust signal: Verified publisher? In-house app? App-only vs delegated? Admin pre-approval?
Use the score to cut the tail: revoke old, unused grants first; re-review broad scopes where offline_access is present.
3) Right-size scopes and split tokens
Developers aren’t villains—they use what’s easy. Offer working patterns:
Prefer read-only scopes when possible (Mail.Read vs Mail.ReadWrite).
Replace tenant-wide scopes with resource-scoped alternatives (e.g., SharePoint site–scoped permissions).
Only request offline_access when absolutely required—and expire or rotate tokens regularly. (Microsoft’s and Google’s docs both explain exactly when refresh tokens are issued and how they behave.) (Microsoft Learn, Google for Developers)
Advanced tip for developers: split interactive and background work so only the background worker asks for offline_access, and with the narrowest scopes.
4) Lock down consent in the first place
Set app-consent policies that:
Restrict user consent to low-risk scopes and verified publishers.
Require admin approval for anything *.ReadWrite.All, directory, mail send, or financial data scopes.
Enable publisher verification requirements and warn on unverified apps.
Microsoft’s Entra guidance is explicit here; start with their recommended defaults and tighten from there. (TECHCOMMUNITY.MICROSOFT.COM)
With Waldo: We surface grants that violate your policy (e.g., offline_access plus a broad write scope from an unverified publisher) and help you mass-revoke or re-scope.
5) Make offboarding automatic and complete
Manual checklists miss long-tail SaaS, personal workspaces, and niche integrations. Wire HRIS → identity → SaaS so that role changes and departures trigger:
Revocation of refresh tokens
Removal of OAuth consents
Deactivation of service accounts tied to the user
Transfer of content ownership
With Waldo: Offboarding flows cover sanctioned suites and long-tail apps, plus API/service accounts—then produce exportable evidence for your audit packet.
Teach your teams “What to look for on consent screens”
This tiny bit of training pays off:
Look for Maintain access to data you have given it — that’s offline_access in human words. If you see it, assume the app will keep access when you’re gone. Microsoft’s consent UI uses precisely this phrasing for offline_access. (Microsoft Learn)
Be allergy-level allergic to *.ReadWrite.All. If “All” is in there, ask why.
Prefer verified publishers. Unknown publisher + offline_access + broad scope = instant red flag.
Use the company app catalog. If you need a new one, ask—fast approvals are part of the deal.
Pair this with a short internal page that says what’s always allowed, what needs a ticket, and what’s never allowed.
What to measure (so the improvement sticks)
Grants with offline_access: total, and % reduced quarter-over-quarter.
High-blast-radius grants: any with *.ReadWrite.All, directory, or mail send scopes.
Unverified publishers with persistence: unverified + offline_access.
Median token age: especially for persistent grants.
Offboarding SLA: median time to revoke all tokens/consents after a role change or exit.
Incident clarity time: time from “we saw unusual activity” to “we know which app, which user, which scopes.”
These are the numbers your GRC, Security, and IT peers can rally around.
A 30-day “permission diet” you can actually do
Week 1 — See it. Aggregate all grants, highlight those with offline_access, and tag by owner/team.
Week 2 — Shrink it. Revoke unused persistent grants. Convert *.ReadWrite.All to read-only where feasible.
Week 3 — Guardrail it. Apply stricter app-consent policies; require admin approval for risky scopes; prefer verified publishers.
Week 4 — Automate it. Wire HRIS to revoke refresh tokens and remove consents on role change/exit; add a monthly report that flags new persistent grants and new broad scopes.
With Waldo, this looks like configuration and bulk actions, not a spreadsheet marathon.
Where Waldo fits (and why teams pick us)
OAuth visibility that finishes: Consolidate tokens and grants across Microsoft 365, Google Workspace, Slack, GitHub, Atlassian, and more. See the scopes, the publishers, the dates, and the usage in one place.
Risk scoring that matches how attacks work: We combine blast radius (e.g., *.ReadWrite.All, directory, mail send) with persistence (offline_access) and trust signals (publisher verification, app-only vs delegated).
Bulk right-sizing and revocation: Swap out broad scopes, remove unused persistent grants, and revoke risky consents—safely and quickly.
Offboarding that actually ends access: Triggered from HR events, including long-tail SaaS and service accounts, with proof for auditors.
Evidence on tap: One-click exports aligned to SOC 2, ISO 27001, HIPAA, and GDPR via our SaaS Compliance Overview. Start by mapping what’s connected with Instant SaaS Discovery.
Further reading & sources
Microsoft identity platform — offline_access scope text and consent phrasing (“Maintain access to data you have given it”). (Microsoft Learn)
Delegated flows & refresh tokens — how apps get refresh tokens to act when the user isn’t present. (Microsoft Learn)
Google OAuth — access_type=offline returns a refresh token for background access. (Google for Developers)
OAuth 2.0 (RFC 6749) — refresh tokens enable new access tokens without user interaction. (IETF Datatracker, OAuth Community Site)
High-privilege Graph permissions — privilege ranking and caution notes for directory-level scopes. (Microsoft Learn)
Consent phishing prevention — Microsoft guidance on app-consent policies and blocking illicit grants. (Microsoft Learn, TECHCOMMUNITY.MICROSOFT.COM)
Bottom line: The most dangerous OAuth permission isn’t just the one that gives you the most power—it’s the one that lets that power persist. Treat offline_access like a multiplier, pair it with least privilege, and automate offboarding so you’re never relying on a password reset to end access. Waldo helps you do all of that without slowing your teams down.