If your company has a single sign-on provider, there's a good chance someone on the security or IT team assumes the SSO dashboard is a reasonably complete picture of what employees use. It almost never is, and the gap between what SSO shows and what's actually running is one of the most useful places to start a shadow IT discovery effort, because the data is already sitting there waiting to be queried.
This is a practical walkthrough for engineers who've been asked to run that audit, or who just want a faster way to answer "what's actually connected to our identity provider" than clicking through an admin console one app at a time.
Why SSO Logs Are a Better Starting Point Than a Survey
Surveys depend on people remembering and being willing to disclose every tool they use. SSO logs depend on nothing except the tool having been connected through the identity provider at least once. That makes the data far more reliable for anything that did go through SSO, even informally, even if the person who set it up never told anyone.
The catch is coverage. Anything authenticated with a personal email address, or with local credentials that never touched SSO at all, won't show up in this data no matter how carefully you query it. Treat an SSO log audit as one input among several, not a complete inventory on its own.
Pulling the Raw Data
Most identity providers expose an events or audit log API that includes application authentication events, not just user logins. Okta and similar platforms typically let you query these events over a rolling window, commonly ninety days by default, sometimes longer depending on your plan tier. Pull the full window rather than relying on the dashboard's summary view. Summary views often deduplicate or roll up in ways that hide low-frequency apps, which are frequently the exact ones nobody remembers signing up for.
GET /api/v1/logs?since=2026-05-01T00:00:00.000Z&filter=eventType eq "user.authentication.sso"
The exact query syntax varies by provider, but the shape is consistent: filter authentication events by type, page through results, and collect the target application for each event alongside the authenticating user.
Building a Deduplicated App List
Once you have raw events, group by target application and count distinct users and total events per app. This single table answers most of the questions that matter: which apps have broad adoption, which have a single user (often a strong shadow IT signal on its own), and which haven't been touched in months but are still technically connected.
from collections import defaultdict
app_users = defaultdict(set)
app_events = defaultdict(int)
for event in sso_events:
app = event["target_app"]
app_users[app].add(event["user_id"])
app_events[app] += 1
for app, users in sorted(app_users.items(), key=lambda x: -len(x[1])):
print(f"{app}: {len(users)} users, {app_events[app]} events")
Sort by user count ascending instead of descending for the discovery pass specifically. The high-adoption apps at the top of a descending sort are almost always already known and approved. The single-user, low-event apps at the bottom are where unsanctioned tools tend to surface.
Cross-Referencing Against Your Known-Good List
The output of the previous step is a raw app list, not a verdict. Cross-reference it against whatever your company already treats as the approved tool list, however informal that list currently is. Anything present in the SSO data but absent from the approved list goes into a review queue, not an automatic ban queue. Some of these will turn out to be legitimate tools that were approved through a channel that never made it onto the master list.
approved = load_approved_app_list()
review_queue = [app for app in app_users if app not in approved]
This is also the point where it's worth checking whether an app on the review queue supports SSO enforcement, not just SSO login. Some apps allow SSO as an optional login method while still permitting a separate password-based login path, which means the SSO log audit will systematically undercount usage for that specific app.
Handling Apps That Don't Use SSO at All
SSO log analysis has a structural blind spot: it can only see what went through SSO. For a fuller picture, pair this method with an expense report scan and a short, blame-free survey. Between the three, you'll catch nearly everything: SSO logs catch anything connected through the identity provider, expense reports catch recurring paid subscriptions regardless of login method, and the survey catches free tools that show up in neither data source.
CISA has published broader guidance on asset discovery methodology that's worth reading if you're building this into a recurring process rather than a one-time pass, and the OWASP project index covers authentication and session handling considerations relevant to any tool you're evaluating for SSO enforcement going forward.
Turning a One-Time Query Into a Recurring Job
A single SSO log audit is useful, but the value compounds when it's automated and run on a schedule. A weekly or biweekly scheduled job that diffs the current app list against the previous run's list will flag new apps almost as soon as they appear, long before they've accumulated enough usage to be an entrenched dependency that's painful to migrate away from.
current_apps = set(app_users.keys())
new_apps = current_apps - previous_run_apps
if new_apps:
notify_security_channel(new_apps)
This kind of lightweight automation turns shadow IT discovery from an annual fire drill into an ambient part of how the security team operates, which is a much cheaper way to run it than a full audit every twelve months.
Common Pitfalls When Running This Analysis
A few mistakes show up repeatedly when engineers run this kind of audit for the first time. The most common is trusting the dashboard's built-in "unique apps" count instead of pulling raw events. Most admin consoles roll up subdomains or slightly different app registrations under a single umbrella entry, which quietly hides the exact granularity you're trying to surface. Always work from the raw event stream, even though it's more tedious to parse.
A second pitfall is treating a low event count as low risk automatically. A tool authenticated only twice in ninety days might be dormant and harmless, or it might be a one-time data export that already happened and can't be undone by revoking access now. Event frequency tells you about usage patterns, not about the risk already incurred. Check what data an app can access before assuming a low-frequency connection is low priority.
A third pitfall is forgetting service accounts and API integrations in the audit scope. Not every SSO event maps to a human clicking a login button. Some map to a scheduled integration authenticating on a service account's behalf, and those often carry broader data access than any individual employee login would. Filter your query results by event subtype early, or you'll spend time investigating machine-to-machine connections that need a different kind of review than a marketing tool a person signed up for.
Building a Dashboard Instead of Running Ad Hoc Queries
Once the audit script proves useful, it's worth the extra afternoon to wire it into a lightweight internal dashboard rather than re-running the same query manually every month. A simple table showing app name, user count, event count, and days since last first-seen, refreshed weekly, gives whoever owns tool governance a live view instead of a point-in-time snapshot that goes stale the moment it's generated.
This doesn't need to be elaborate. A scheduled job writing results to a shared spreadsheet or a small internal database, paired with a Slack notification when a genuinely new app appears, covers most of the value a dedicated security tool would provide, at a fraction of the engineering cost. The goal is visibility that persists, not a one-time report that gets read once and then forgotten in a shared drive.
What to Do Once You Have the List
Finding unsanctioned apps is the easy part. Deciding what happens to each one, and doing it in a way that doesn't push the next round of tool adoption further underground, is the harder part and the one that determines whether this exercise actually reduces risk over time. 137Foundry has written a longer breakdown of the discovery-to-governance process, including how to run the decision phase without turning it into a witch hunt, in its guide on identifying and reining in shadow IT.
The short version: SSO log analysis gets you a fast, reliable, low-effort starting point. What you build on top of it, the review cadence, the ownership, the faster approval path for legitimate requests, is what actually keeps the problem from coming back six months later.
None of this requires a security team of any particular size. A single engineer with API access to the identity provider and a couple of hours can produce a more accurate picture than most companies have ever had, and turning that one-time script into a scheduled job is a small additional step that pays for itself the first time it catches a new unsanctioned app before it becomes an entrenched dependency nobody wants to migrate away from.
Top comments (0)