๐ฑ Recipe ยท Intune & Device Management
Identify Non-Compliant or Unenrolled Devices Accessing Corporate Data
Audit Entra ID sign-in logs against Intune enrollment and compliance state to surface unmanaged devices touching SharePoint, OneDrive, and other corporate resources
Complexity
Advanced
Impact
security + compliance + audit + intune + conditional-access
Context
Why This Matters
Conditional Access and Intune compliance policies are only effective if every device touching corporate data is actually enrolled and evaluated. In practice, gaps open up quickly: personal phones that slipped past enrollment, contractor laptops, legacy devices that fell out of compliance, or sign-ins where Azure AD could not capture a device ID at all.
This recipe correlates two data sources โ the Intune managedDevices inventory and the Entra ID signIns audit log โ to produce a single report of every user/device pair that accessed corporate data in the last 7 days while being either non-compliant or not enrolled. SharePoint Online and OneDrive access is flagged separately because those workloads typically host the most sensitive data.
When to run it:
- Weekly or monthly as part of a device hygiene review
- Before tightening a Conditional Access policy to require compliant devices (to understand blast radius)
- After a compliance baseline change, to find devices that fell out of compliance
- During incident response when unmanaged access is suspected
Expected Outcomes
After running this recipe you will have:
- A CSV report of every non-compliant or unenrolled device that accessed corporate data in the last 7 days, grouped by user and device
- A count of sign-ins per device and the specific resources accessed (SharePoint, Exchange, Teams, etc.)
- A separate flag column highlighting devices that accessed SharePoint Online or OneDrive
- A list of currently enrolled-but-non-compliant devices from Intune for remediation
- Enough evidence to justify (or scope) a Conditional Access policy requiring device compliance
Risks & Considerations
Data volume and API throttling
The signIns endpoint can return tens of thousands of records per week in a mid-sized tenant. Always paginate with @odata.nextLink and cap your result set (e.g. 10,000 rows) to avoid throttling (HTTP 429). Add a $top=500 to reduce round trips.
Device ID correlation is imperfect
Not every sign-in has a deviceDetail.deviceId. Sign-ins from browsers in private mode, legacy auth, or some mobile apps will have a blank device ID. Treat these as Unknown (No Device ID) rather than assuming they are safe.
Do not enumerate SharePoint sites by display name
The Graph /sites endpoint does not support tenant-wide enumeration via $filter=contains(displayName,...). Use the resource names that appear in the sign-in log (Office 365 SharePoint Online, OneDrive) as your sensitivity signal instead, or cross-reference against a curated list of sensitive site IDs you maintain separately.
Licensing
Reading sign-in logs via Graph requires Entra ID P1 or P2. Without it, the /auditLogs/signIns endpoint returns 403.
Privacy and retention
Sign-in logs contain IP addresses, locations, and user identities. Handle the output CSV as confidential and follow your data retention policy before archiving.
Do not act on the report without review
Some "unmanaged" sign-ins are legitimate โ service accounts, break-glass accounts, or approved BYOD covered by App Protection Policies rather than MDM. Review before blocking.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| DeviceManagementManagedDevices.Read.All | Read the Intune managed devices inventory and their compliance state |
| AuditLog.Read.All | Read Entra ID sign-in logs for the correlation window |
| Directory.Read.All | Resolve user principal names and device directory objects referenced in sign-in logs |
| Sites.Read.All | Optionally resolve SharePoint site metadata when correlating against a curated sensitive-site list |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
Manual walkthrough using the Microsoft admin portals
This is a multi-portal workflow. There is no single pane of glass for this correlation โ you will pull each dataset and reconcile them in a spreadsheet.
Step 1 โ Export Intune device compliance
- Sign in to the Microsoft Intune admin center.
- Navigate to .
- Click Columns and ensure Compliance, OS, Primary user UPN, Azure AD Device ID, and Model are visible.
- Click Export to download the device list as CSV. This is your enrollment + compliance baseline.
Step 2 โ Review non-compliant devices
- Still in Intune, go to .
- Note the count and export the list. These are enrolled but failing policy โ remediation candidates.
Step 3 โ Pull sign-in logs from Entra ID
- Open the Microsoft Entra admin center.
- Go to .
- Set the date filter to Last 7 days.
- Add filters: Status = Success, and optionally Application contains SharePoint to scope to SharePoint access.
- Click Download > JSON or CSV. Include the Device and Device ID columns.
Step 4 โ Correlate in Excel or Power BI
- Open both exports. In the sign-in log, add a lookup column:
VLOOKUP(DeviceId, IntuneExport!AzureADDeviceId, ComplianceState). - Filter rows where the lookup returns #N/A (not enrolled) or noncompliant.
- Add a flag column:
=IF(ISNUMBER(SEARCH("SharePoint",ResourceDisplayName)),"โ ๏ธ SharePoint",""). - Sort by the SharePoint flag, then by sign-in count per user/device.
Time estimate: 30โ45 minutes for a tenant under 500 devices. The API/script paths below do the same work in under a minute.
Graph API recipe
Three Graph calls, joined in memory. All paths below are relative to https://graph.microsoft.com.
1. List managed devices with compliance state
GET /v1.0/deviceManagement/managedDevices?$select=id,deviceName,userPrincipalName,complianceState,operatingSystem,model,azureADDeviceId&$top=200Paginate via @odata.nextLink. Build a dictionary keyed on azureADDeviceId (lowercased) for fast lookup.
Note: isRooted is not selectable on the v1.0 or beta managedDevice type โ do not add it to $select or the request returns HTTP 400.
2. Query successful sign-ins for the last 7 days
GET /v1.0/auditLogs/signIns?$filter=createdDateTime ge 2025-01-15T00:00:00Z and status/errorCode eq 0&$select=createdDateTime,userPrincipalName,deviceDetail,resourceDisplayName,appDisplayName&$top=500Example response fragment:
{
"createdDateTime": "2025-01-20T14:32:11Z",
"userPrincipalName": "alice@contoso.com",
"resourceDisplayName": "Office 365 SharePoint Online",
"appDisplayName": "OneDrive",
"deviceDetail": {
"deviceId": "b5976a7e-2fbd-47f8-8e28-86af883c720f",
"displayName": "LAPTOP-42",
"operatingSystem": "Windows 10",
"isCompliant": false,
"isManaged": false
}
}3. Join and filter
For each sign-in, look up deviceDetail.deviceId in the managed devices dictionary:
- Match + compliant โ skip (healthy)
- Match + noncompliant โ flag as Enrolled, Non-Compliant
- No match โ flag as Not Enrolled
- Empty deviceId โ flag as Unknown (No Device ID)
Then flag any row where resourceDisplayName or appDisplayName contains SharePoint or OneDrive as sensitive-data access.
Throttling
If you get HTTP 429, honor the Retry-After header. Cap your result set at ~10,000 sign-ins and narrow the $filter further (e.g. by appDisplayName) if you exceed that.
PowerShell recipe with Microsoft.Graph SDK
This script does the full correlation in one run: pulls Intune devices, pulls 7 days of sign-ins, joins them, and exports a CSV with SharePoint flagging.
Prerequisites
- PowerShell 7+
Microsoft.GraphSDK installed:Install-Module Microsoft.Graph -Scope CurrentUser- Entra ID P1 or P2 license (required for sign-in log access)
- Consented scopes:
DeviceManagementManagedDevices.Read.All,AuditLog.Read.All,Directory.Read.All
Running it
# Default: last 7 days, CSV to current directory
.\Get-NonCompliantDeviceAccess.ps1
# Custom window and output path
.\Get-NonCompliantDeviceAccess.ps1 -DaysBack 14 -OutputPath C:\Reports\device-access.csv
# Focus only on SharePoint/OneDrive access
.\Get-NonCompliantDeviceAccess.ps1 -SharePointOnlyWhat the script does
- Connects to Graph with the required scopes (delegated or app-only).
- Pages through
/deviceManagement/managedDevicesinto a hashtable keyed onazureADDeviceId. - Pages through
/auditLogs/signInsfiltered to successful sign-ins in the time window. - For each sign-in, looks up the device and classifies it as Enrolled/Compliant, Enrolled/Non-Compliant, Not Enrolled, or Unknown.
- Flags sign-ins against SharePoint Online or OneDrive as sensitive-access.
- Groups by user+device, computes counts, and writes a CSV sorted with the highest-risk entries first.
Expected output
A CSV similar to:
User,DeviceName,DeviceId,OS,EnrollmentStatus,ComplianceState,TotalAccesses,SharePointAccesses,RiskFlag
alice@contoso.com,LAPTOP-42,b5976a7e-...,Windows 10,Not Enrolled,N/A,27,22,โ ๏ธ SharePoint Access
bob@contoso.com,SBI-IPAD-...,iPad Pro 13,iOS,Enrolled,noncompliant,14,8,โ ๏ธ SharePoint AccessNext steps