The gap your CASB was never built to see
Shadow OAuth is the distance between what your CASB logged and what your identity provider already authorized. An employee clicks Allow. The vendor stores a refresh token. That token works at 2 a.m. from a data center you do not own, while the laptop is off and the VPN is down. Finance may never see an invoice. The product is freemium. Procurement never opened a ticket. The grant is still there, with whatever scopes were on the consent screen.
Security teams usually find this during a breach, not during a calm Tuesday. Salesloft Drift, Context.ai, and the connector campaigns of 2024 all used grants that lived in a vendor vault. Your SOC was watching the network edge. The traffic never came through it.
This guide is the data path, why SIEM and CASB rules miss it, and a procedure you can run in Google Admin and Okta this week. Then I will show where ScopeMantle turns a one-off export into a daily diff. We do not need you to rip out the CASB. We need you to stop pretending it inventories refresh tokens.
How the data path actually works
Authorization starts in the browser. The user hits accounts.google.com or the Okta authorize endpoint. A CASB or SWG can see that first hop if the device is enrolled and the PAC file is honest. After consent, the SaaS vendor exchanges the code on its servers and keeps the refresh token. From that point, Gmail reads and Drive syncs originate from the vendor's AWS (or equivalent) region. They look like vendor-to-Google HTTPS. They are supposed to.
You cannot MITM Google at scale to fix this. You would break device trust, break certificate pinning, and still miss tokens issued before the proxy existed. ZTNA has the same blind spot. It brokers human sessions. It does not sit on Context.ai's call to Google's token endpoint.
| Control | What it sees | What it misses |
|---|---|---|
| CASB / SWG | Browser consent, if proxied | Vendor-to-IdP refresh after the token exists |
| SIEM login use cases | Human auth: travel, MFA fatigue, privilege | Machine refresh that looks like the integration working |
| MDM / EDR | The laptop, the extension ID if you look | Tokens already stored in the vendor vault |
| SCIM / SSO catalog | Apps you provisioned on purpose | User-consent OAuth that never created an app tile |
| IdP grant APIs | Client ID, scopes, owner, often last used | Nothing about this class, if you actually export it |
SIEM correlation can help after you have grant metadata. It cannot invent a client ID that never landed in a log. That is why inventory is an identity problem first.
Why the volume jumped
Remote work killed the "go ask IT for a license" friction. OAuth replaced the ticket queue with one click. AI copilots and browser extensions asked for mail and Drive because summaries are useless without content. Between 2023 and 2026 a lot of enterprises watched grant counts climb without a matching climb in POs.
Department budgets fund RevOps and martech outside the IT catalog. Shadow OAuth is shadow IT at the identity layer, and it is worse than an unapproved binary on a laptop. The token works when the laptop is in a drawer.
What Google Admin and Okta actually give you
Google Admin lists connected apps under Security, then Access and data control, then API controls, then Manage third-party app access. You get client name, client ID, user count, and scopes. You do not get a composite risk score, an attestation workflow, or a cross-IdP join with Okta. User-level detail means drilling into each app. Budget half a day at 500 employees if you are thorough.
Okta's Admin APIs expose OAuth clients for Okta-as-IdP. They miss Google-native grants when someone OAuths a SaaS tool with their Google account and never touches Okta. Multi-IdP shops that only export one side tell themselves a comforting lie.
Spreadsheets rot. Owners leave. Vendors rebrand. Client IDs stay stable; your row does not. A quarterly CSV is better than nothing. It is not a control.
Manual discovery you can run this week
- Export Google third-party app access. Keep client ID as the primary key.
- Export Okta OAuth clients and any "Admin approved" vs user-consent split you have.
- Join on email domain of grant owners. You will find people in both lists and people in only one.
- Flag mail, Drive, calendar, and admin.directory scopes. Those are the blast-radius rows.
- Compare user count to HRIS headcount. Grants covering more people than you employ are leftover accounts.
- Cross-check terminated employees. Any live grant is a finding waiting for CC9.2 sampling.
- Sort into sanctioned, tolerated shadow, and revoke-now. Write the rule down. Auditors prefer a documented exception to a silent allow-all.
- Revoke three obvious outliers (unknown Chrome extension, wallpaper app with mail read, tool with zero last-used in a year). Tell the owners first unless you are in active IR.
Chrome enterprise policy is upstream of Admin. An allow-list on extension IDs stops the Context.ai class before consent. Pair it with the Admin grant list. One without the other is how extensions lived outside "Apps with access" until someone clicked Allow.
Worked examples
BYOD plus corporate Google. MDM sees the device. It does not see the personal Chrome profile that authorized a summarizer against the work account. That is a double blind. Policy has to name both controls.
Engineer's personal GitHub. Corporate Google SSO to github.com appears as a Workspace grant. That is a different object from GitHub org SSO you already review. Do not skip it because "we already do GitHub."
PAC exception myth. Someone will tell you that sending Google domains direct (no proxy) is fine because Google is trusted. That exception is exactly how you lose the only hop the CASB could have seen. Document it in the architecture review as a choice, not an accident.
Building identity-native inventory
Connect read-only Google Workspace and Okta APIs to ScopeMantle. First sync lists every grant: client ID, vendor name, scopes, owner, created date, last used if the API provides it. No endpoint agent. Microsoft Entra is Beta on the roadmap. Do not plan a multi-IdP program as if Entra were GA.
Risk scoring applies four dimensions. Scope Sanity compares scopes to vendor category. Security and Privacy use public attestation and published practices. Breach History moves when a vendor discloses. Scores below forty queue in governance for attestation or auto-revoke, if you turned that policy on.
Assign owners by business unit. Marketing owns martech grants. Engineering owns devtools. A weekly digest of new unattested installs beats the annual panic the week before fieldwork. Pair review with the deprovisioning model: HRIS termination has to revoke grants, not only disable the IdP session. Export the board slide quarterly: total grants, percent attested, count below threshold.
CASB and ScopeMantle in the same stack
Keep the CASB. It is still the right tool for unmanaged browsing and DLP on managed egress. Once inventory names a bad client ID, proxy policy can block the consent page. That is a closed loop, not a replacement story.
Ask your CASB vendor a precise question: do they inventory refresh tokens at the IdP, or only SaaS accounts provisioned via SCIM? Most OAuth modules are the second thing with a new label. Verify before you retire a spreadsheet you at least understood.
Failure modes
- Consent-screen literacy is zero. People click Allow because the button is blue. Training that only covers phishing misses this.
- Vendor questionnaires never ask how refresh tokens are stored or rotated. Add the question when a new grant is unattested.
- Reports API scripts die on quota Monday morning and nobody notices a half CSV. Google Admin remains the manual source of truth until a connector handles backoff.
- Block-everything policies push people onto personal Gmail. You lose visibility and you do not reduce data leaving the company. You just stop seeing it.
- Permanent exceptions. Ninety-day expiry or it is not a control.
What to tell an auditor
CC9.2 is vendor delegate access, not CC6.7 user login. Say that out loud in the kickoff. Offer an IdP grant export with client ID and scopes, plus attestation dates. If they ask whether the CASB covers OAuth, answer with the data-path paragraph above. Do not claim ScopeMantle is HIPAA attested. We are not. No BAA.
What to do this week
- Export Google Admin third-party apps. Revoke five unattested high-scope rows you cannot explain.
- Write a one-page architecture note: "OAuth refresh bypasses CASB and ZTNA. Identity inventory is the control." Put it in the last architecture review deck.
- Turn on Chrome extension allow-list in a sandbox OU. Measure the ticket volume before you go company-wide.
- Name app owners for martech and engineering. If nobody will sign, that is your first metric.
- Read the supply-chain playbook, the Context.ai breakdown, and the SOC 2 checklist. Trial ScopeMantle if you do not want to babysit the export.
Awareness training that is not a phishing video
One slide in security awareness: a real consent screen with gmail.readonly highlighted, and the sentence "this works when your laptop is off." That is more useful than another password-length cartoon. Give people an approved request path with a 48-hour SLA. If the SLA is two weeks, they will click Allow and you will deserve the inventory you get.
Vendor questionnaires should ask where refresh tokens live, who can admin the OAuth app, and how fast they revoke on a disclosed breach. Send that questionnaire when a new grant appears, not once a year for the logos finance already knows.
Honest limits
Standard is $5 per employee per month annual or $6 monthly. No seat minimum. Custom at 500+. Thirty-day full-platform trial via /demo. No fabricated logos on customers. Entra is Beta. HIPAA is not attested. Event stream to SIEM is optional; a weekly digest is enough for most mid-market teams. Related: Google vs Microsoft vs Okta and third-party identity attack surface.
Reports API and Admin SDK quotas will bite Monday-morning cron jobs. If you script this, handle backoff or accept a half-written CSV. ScopeMantle incremental sync exists because silent half-exports are how inventories rot. Chrome Web Store IDs and Google OAuth client IDs are different identifiers. Record both when the tool is an extension.
Grant the security team a delegated app-access admin role, not super-admin, for daily reviews. Super-admin sampling stays a CC6.1 exercise. Mixing those roles makes both workpapers messy and raises the blast radius of a compromised reviewer account. If the only person who can export grants is also the only super-admin, you have an availability problem disguised as an identity program. Name a deputy. Rehearse the export on their account before vacation.
Field guide: the architecture review slide
One diagram: browser consent hop (CASB maybe sees it), vendor vault, vendor-to-IdP refresh (CASB does not). One sentence: inventory is the control. One ask: export Admin this week and name app owners. $5 / $6, no seat min. Why-now.