Scopes define exactly what an OAuth grant can do. They're just written in a language nobody bothered to translate.
Every OAuth grant comes with fine print. It's called a scope, and it defines exactly what the grant is allowed to do. The problem is that scopes were never written for humans. They're programmatic definitions of permissions, designed for machines to enforce, not for people to understand.
‍
If you're assessing the risk of an OAuth grant, the scopes are the whole story. And most of the time, the story is written in a language nobody bothered to translate. Worse, the scope string is only half the picture. The same permission granted by an individual contributor and by a Google Workspace admin produces wildly different blast radius, and nothing in the scope name tells you which one you're looking at.
‍
When a user authorizes an OAuth grant, the permissions attached fall into two buckets.
‍
The first is identity-only scopes. These are the standard OpenID Connect scopes where one provider is simply asserting the user's identity to another: email address, first name, last name, profile photo. This is what most "Sign in with Google" flows request. The receiving app learns who you are and nothing more.
‍
The second bucket is everything else: custom scopes defined by each platform. Google publishes hundreds of them. Microsoft Graph publishes 951. Salesforce, Slack, GitHub, Atlassian, every SaaS platform with an API has invented its own permission vocabulary. There's no standard and no requirement that any of it be legible.
‍
Some platforms make an effort. Google's gmail.readonly tells you roughly what you're getting: read access to email. You can infer the permission from the string itself.
‍
Then there's the other end of the spectrum, where a scope is a machine-generated string or a bare UUID. Open a Microsoft Entra app manifest and the permissions are listed as GUIDs, not names. No hint of what they do. No way to reason about them from the string.
‍
Your only option is to go find the platform's documentation. That's where it gets worse. The docs are scattered, thin, and inconsistently maintained. There's no central registry of scopes across the SaaS ecosystem. Every platform documents its own permissions in its own corner of its developer docs, if it documents them at all.
‍
The consent screen should be the safety net here, and it isn't. Every platform provides some level of user consent, but the usability varies wildly. More often than not it's a laundry list of permissions that users click through without reading. We've trained an entire workforce to treat the consent screen like a EULA: scroll, accept, move on.
‍
Cut through the naming chaos and nearly every scope on every platform boils down to one of two things:
Being able to quickly sort a grant's scopes into these two categories is the first real step in understanding it. A grant that can read your calendar is a different risk than a grant that can send email as you. The scope strings won't always make that distinction obvious, but the distinction is always there.
‍
Here's the piece that gets missed most often. A scope defines what a grant can do, but not how far that reaches. That depends entirely on who granted it.
‍
With very few exceptions, OAuth grants delegate the access of the user who created them. The scope doesn't shrink or expand on its own; it inherits. An email.readonly scope granted by an individual contributor means access to one person's mailbox. A directory scope granted by a Google Workspace admin can mean read access to your entire user directory. Same protocol, same consent flow, wildly different blast radius.
‍
GitHub is the notable exception. Fine-grained tokens let a user narrow a grant to a single repository instead of everything they can touch. Google offers something similar with drive.file, which limits an app to the files a user explicitly opens with it. But these are the exceptions, and most users never choose them. Almost everywhere else, the grant gets whatever the user has, and admin users grant admin-sized access.
‍
So when you're analyzing a grant, the scope list is only half the input. The other half is the identity and privilege level of the grantor. An innocuous-looking scope granted by the wrong person is often the riskier finding.
‍
If you're going to reason about OAuth grants at scale, you need the raw scopes for every grant, not just a list of which apps are connected. Two grants to the same app can carry very different permissions. You also need reference material for every platform you operate on. Since the documentation is scattered, someone has to map opaque scope strings to effective permissions, and that context should show up right alongside the scopes when you're doing the analysis, not three browser tabs away in a developer doc.
‍
From there, two questions do most of the triage work:
Scopes are the closest thing we have to a permission slip for the Workforce Edge, the sprawl of SaaS and AI apps your employees connect every day. They're just written in a way that guarantees nobody reads them. The platforms aren't going to fix that. So translate the fine print yourself: pull the raw scopes for every grant, sort them into data versus action, and check who granted them. An innocuous scope in the hands of an admin is usually the finding that matters.
‍