OAuth grant sprawl is the buildup of third-party app permissions that users have approved over the years and that keep working long after the employee, the app or the business need has gone. Good OAuth token management controls it by deciding which apps may be approved at all, keeping the permissions they receive small, reviewing them on a schedule, and revoking them when a person leaves. Because the approval is stored separately from the user’s password and MFA, none of your sign-in controls will remove it for you.
A quick definition keeps this post separate from the protocol theory you may have searched for. In this article, a “consent grant” means the stored decision where a user or administrator allowed a specific application to act on their behalf with specific permissions, and the refresh tokens and access tokens that follow from it. It does not mean the OAuth “grant types” such as authorization code or client credentials, which describe how an app obtains a token. The OAuth 2.0 framework in RFC 6749 covers those, and our explanation of OAuth scopes covers how permissions are named and requested.
What is OAuth grant sprawl?
Grant sprawl is persistent delegated access: an app holds a token that lets it read mail, files, calendars or messages as a user, and nobody is tracking whether that is still wanted. In OAuth 2.0, the user authorizes a client, and the client receives tokens it can use without the user being present. RFC 6749 describes refresh tokens as credentials used to obtain new access tokens when the old ones expire, which is what lets an approval last for months or years rather than for one session.
Sprawl develops gradually. A team trials a meeting-notes tool, a sales rep connects a scheduling add-on, a developer authorizes a command-line tool against the company directory, and each of these creates a grant. People change roles, trials end and vendors get acquired, but the grant stays in place until someone removes it. The result is access that no longer matches any current business reason, which is why people also call it shadow access or token sprawl.
Why don’t MFA and SSO revoke an approved grant?
MFA and single sign-on protect the moment of authentication, but an OAuth grant is authorized once and then used by the application with its own tokens. A refresh token does not ask for a password or a second factor each time it is exchanged, so adding MFA after the fact, or resetting the user’s password, does not necessarily invalidate what the app already holds. RFC 9700 only says an authorization server MAY revoke refresh tokens on a password change, so whether the grant stops working depends on the provider.
This is why consent grants matter next to stolen-session attacks. In our post on session hijacking with infostealers, the attacker avoids the login and reuses something already issued, and an approved grant is another kind of already-issued access. The OAuth 2.0 Security Best Current Practice, published as RFC 9700, responds to this class of problem by recommending that refresh tokens issued to public clients be sender-constrained or rotated on every use, and that the privileges of each access token be restricted to the minimum the use case requires. Those controls reduce what a leaked token can do, but they do not replace a review of who approved what.
How does one consented app become a foothold?
The usual pattern is that an attacker or a careless vendor ends up holding a token that was legitimately issued. An employee approves an app, either because it looks routine or because a phishing message tricked them into doing so, and the app, or whoever controls it, stores the token and later uses it to read data through the provider’s API, often without a sign-in event that a login-focused alert would notice.
Tricking someone into approving a malicious app is called consent phishing, and it works because the screen the user sees is the real provider’s consent page. It is closely related to device code phishing, where the user is persuaded to approve a sign-in on a legitimate page, and to the attacks covered in what account takeover is. The common thread is that the victim never types a password into a fake site, so training users to check URLs does little here.
A compromised vendor produces the same result without any phishing at all. If a third-party app’s token store is breached, every customer who granted that app access is exposed at once, and customers often learn about it only when the vendor discloses the breach. This is why it matters to know which apps hold tokens, not just which users have accounts.
Where do OAuth grants live in your environment?
Each platform keeps its own list, and there is no single place to look. The table below summarizes the usual locations, and each deserves a check because the controls differ by vendor.
| Platform | Where grants are stored | What an admin can usually do |
|---|---|---|
| Google Workspace | Per-user authorized apps, plus admin API controls | Restrict which third-party apps can access which Google data, and review app access |
| Microsoft 365 / Entra ID | Enterprise applications and user consents | Limit user consent, require admin approval, remove an app’s permissions |
| Slack | Installed apps per workspace | Require app approval, remove installed apps |
| Salesforce | Connected apps and user OAuth usage | Block or pre-authorize connected apps, revoke tokens |
| Your own IdP | Client consents and offline tokens | Require consent, revoke consent and sessions |
Google documents these controls in its Workspace admin help on controlling which third-party and internal apps access Workspace data, and Microsoft describes the review process in its admin consent workflow documentation. Check the current documentation for your tenant, since menu names and defaults change.
The last row is easy to overlook. If your own product lets customers connect integrations, the grants your users approve against your identity provider are part of your customers’ sprawl, and your customers will expect to see and revoke them.
How does OAuth token management govern grants?
A workable approach treats grants as an inventory with an owner and a review cycle, in four parts.
- Gate approval with an admin consent workflow. An admin consent workflow means that when a user wants an app that asks for sensitive permissions, the request goes to a designated reviewer instead of being approved by the user alone. Microsoft Entra supports this directly, and Google Workspace and Slack have comparable app-approval controls. Allow users to self-approve only low-risk permissions from verified publishers.
- Keep scopes small. Ask what the app needs to do and grant only those scopes. Read-only calendar access is a very different risk from full mailbox access, and RFC 9700 recommends restricting tokens to the minimum privileges required.
- Reauthorize on a schedule. We suggest asking for reauthorization at regular intervals, for example every 90 days for high-risk apps. This is a policy suggestion rather than a standard, and the right interval depends on how sensitive the data is and how much friction your users will tolerate.
- Put revocation in the offboarding checklist. When someone leaves or changes role, remove the grants they approved, not only their account. Our post on user provisioning covers how lifecycle automation can include this step, and the checklist should name each platform in the table above.
Revocation itself has a standard. RFC 7009 defines an endpoint where a client can tell the authorization server that a token is no longer needed, so the server invalidates it (admin-side revocation of a user’s grants happens in each provider’s console or admin API, not through this endpoint), and RFC 7662 defines token introspection, which lets a resource server ask whether a token is still active. Revocation only helps if resource servers actually check token state or keep access token lifetimes short, so confirm which of the two your APIs rely on.
What should your customer-facing identity provider expose?
If you run an identity provider for your customers, the same governance questions apply to the apps your customers’ users approve. A customer security reviewer will reasonably ask whether you can show and remove what they have authorized. A useful minimum is the following.
- Clear consent screens. The user should see the app name, the publisher and a plain description of each permission, so a consent decision is an informed one.
- Deliberate client and scope design. Each integration should have its own client, with scopes that match what it does, rather than one broad client shared by several tools.
- Revocation interfaces. Users and administrators should be able to revoke a consent, and administrators should be able to do it for a departed user without that user’s cooperation.
- Audit events. Record when consent is granted, when tokens are issued and refreshed, and when grants are revoked, so you can answer “who approved this and when” after the fact.
How do you manage consent and tokens in Keycloak?
Keycloak, the open source identity and access management project that Skycloak hosts, covers most of the controls above, with details that you should confirm against the release you run (the current line is 26.x). The four below matter most for grant governance.
First, each client has a “Consent required” setting. When it is on, users see a consent screen listing the requested scopes and must approve before the client receives a token. Users can later review and remove their approvals from the Applications page of the Account Console, and administrators can view and revoke a user’s consents from the user’s page in the Admin Console.
Second, use confidential clients (client authentication turned on) for server-side integrations, so the client secret or another credential is needed to redeem codes and refresh tokens. Public clients such as single-page apps cannot keep a secret, which is why RFC 9700 requires them to use PKCE with the authorization code flow and to use sender-constrained or rotating refresh tokens.
Third, Keycloak supports client policies, which let you apply requirements across groups of clients, for example requiring PKCE or restricting which flows a client may use. This is the right place to encode a rule once instead of reviewing each client by hand. See the Keycloak documentation on client policies for the executors available in your version.
Fourth, handle departures explicitly. Disabling a user blocks new logins and token refreshes, but access tokens already issued stay valid until they expire, so also end the user’s sessions and revoke their consents and offline tokens. Offline tokens are refresh tokens that do not expire with the browser session, and they are revocable from the user’s Consents tab in the Admin Console and listed per client on the client’s Offline Access tab. The same session controls matter for the attacks in our MFA fatigue hardening guide, and the rogue external MFA write-up shows why identity provider configuration deserves the same review as the applications.
Which grant types need extra scrutiny?
Some flows deserve closer review because the user approves on a different device from the one that receives the token. The device authorization grant (RFC 8628) shows a short code on one device that the user enters on another, which is exactly the step device code phishing abuses. Client-Initiated Backchannel Authentication (CIBA, from the OpenID Foundation) sends an approval request to the user’s separate authentication device, which makes prompt-fatigue and misdirected approvals a concern. If you do not need either flow, disable it per client.
The direction of the standards is toward less implicit trust. Our summary of upcoming changes in OAuth 2.1 covers the removal of weaker flows, which reduces the number of grant types you have to defend.
Frequently asked questions
Does resetting a password or enabling MFA revoke OAuth access?
Not necessarily. Tokens an app already holds are separate from the user’s password and second factor, and a refresh token can keep working until it expires or is revoked. Check how your provider behaves on password reset, and revoke grants and sessions explicitly as part of any account recovery or offboarding.
How often should we review OAuth grants?
There is no standard interval. One reasonable starting policy is a quarterly review, with reauthorization about every 90 days for apps that can reach sensitive data, and an immediate review whenever an employee leaves or an app vendor reports a breach. Adjust to the sensitivity of the data and your users’ tolerance for repeated prompts.
How can we tell if a user approved a malicious app?
Look for new enterprise or connected apps with broad scopes, unfamiliar publishers, or consent events from users who would not normally install integrations. Reviewing the consent and audit logs on each platform, and requiring admin approval for high-risk permissions, helps you catch these approvals early.
Where to start
Start with an inventory: list the third-party apps with access on each platform, note who approved them and what they can reach, and remove anything without a current owner. Then require admin approval for sensitive scopes, add grant revocation to your offboarding checklist, and schedule a recurring review. If you operate an identity provider for customers, make sure consent, revocation and audit events are visible to them, since they will have the same sprawl problem inside their own organizations. If you would rather not run that infrastructure yourself, our pricing page shows what managed Keycloak on Skycloak includes.