For years, defenders relied on MicrosoftGraphActivityLogs to monitor Graph API activity in Microsoft Entra ID. However, this visibility was incomplete because the table only captures requests to Microsoft Graph (graph.microsoft.com) and does not include activity against the legacy Azure AD Graph endpoint (graph.windows.net). The newly introduced AADGraphActivityLogs table closes this long-standing telemetry gap.

The missing visibility relates to the legacy Azure AD Graph API, which is still used by many enterprise applications, including some Microsoft services.

For security teams, threat hunters, and SOC analysts, this significantly improves detection visibility.

Why another table?

Many defenders assumed that monitoring MicrosoftGraphActivityLogs meant they had visibility into all Graph-related activity within their tenant. In reality, this is not true. Time to make it clear.

In reality, MicrosoftGraphActivityLogs only captures traffic to Microsoft Graph (graph.microsoft.com).

It does not provide visibility into requests made to the legacy Azure AD Graph API (graph.windows.net).

The distinction is important:

Log TableAPI Endpoint
MicrosoftGraphActivityLogsgraph.microsoft.com
AADGraphActivityLogsgraph.windows.net (Legacy Azure AD Graph)

This separation created a telemetry gap that attackers and security assessment tools could unintentionally or deliberately leverage.

Why is this still in use?

A large number of well-known Azure AD reconnaissance and assessment tools were built around the legacy Azure AD Graph API. Just some popular toolings that were using the legacy API.

  • AADInternals
  • ROADtools / ROADrecon
  • Ping Castle

These tools are commonly used by:

  • Red teams
  • Penetration testers
  • Adversaries performing cloud reconnaissance
  • Security consultants assessing identity posture

Because many of these tools communicate directly with graph.windows.net, their activity often never appeared in MicrosoftGraphActivityLogs, since, as already explained, the API used in the toolings is the legacy graph.windows.net API.

As a result, organizations could have significant identity reconnaissance activity occurring in their environment while SOC analysts remained unaware because they were monitoring only Microsoft Graph telemetry or were focusing on Defender (EDR/AV) alerts.

So why are we making such a big deal about a log for an API that Microsoft has been trying to retire for years? Attackers still love old legacy Azure AD Graph APIs, since there is no logging. And no logs means no visibility, and without visibility, there is no detection.

Why Legacy Azure AD Graph Still Matters

Despite Microsoft’s push toward Microsoft Graph, many environments continue to have dependencies on Azure AD Graph. Common reasons include:

Legacy Enterprise Applications

Applications developed years ago may still depend on Azure AD Graph APIs and have never been modernized.

Older Automation Scripts

PowerShell scripts, custom tooling, and operational automations often continue running long after their original deployment.

Deprecated Integrations

Third-party products sometimes maintain legacy integrations for compatibility reasons.

Technical Debt

Organizations frequently discover Azure AD Graph dependencies only when they begin migration projects or API retirement efforts.


AADGraphActivityLogs

The new AADGraphActivityLogs table finally provides defenders with visibility into traffic directed at the legacy Azure AD Graph endpoint. That means security teams can now detect legacy reconnaissance activity and improve their threat/ detection capabilities.

Many organizations are unaware of how much legacy Azure AD Graph usage still exists within their environments. The new table can help identify:

  • Legacy enterprise applications
  • Old automation workflows
  • Deprecated scripts
  • Outdated integrations

When enabling the audit logs, it can provide direct logging into the legacy graph telemetry. Based on the logging, usage can be detected.

How to connect the new source?

The new logging can be enabled as part of the Entra Diagnostic settings. Entra -> Diagnostic settings. In the available log categories, you can find the AzureADGraphActivityLogs

The following graph-related logs are available in the diagnostic settings:

TableWhat it CapturesAPI / Service
MicrosoftGraphActivityLogsRequests made to Microsoft Graphgraph.microsoft.com
AzureADGraphActivityLogsRequests made to legacy Azure AD Graphgraph.windows.net
GraphNotificationsActivityLogsGraph change notifications (webhooks/subscriptions)Microsoft Graph subscriptions
MicrosoftGraphPolicyLogsPolicy enforcement and governance actions related to Graph accessMicrosoft Graph
PreAuthenticationDiscoveryLogsDiscovery activity occurring before authentication, often used during reconnaissance or app discovery workflowsIdentity/Graph-related discovery processes

As SOC reference:

QuestionTable
Who queried Microsoft Graph?MicrosoftGraphActivityLogs
Who queried Azure AD Graph?AzureADGraphActivityLogs
Who created Graph webhooks/subscriptions?GraphNotificationsActivityLogs
Why was Graph access allowed or governed?MicrosoftGraphPolicyLogs
Who performed tenant/user discovery before login?PreAuthenticationDiscoveryLogs

Select the AzureADGraphActivityLogs checkbox and send the logs to your Log Analytics workspace. Once enabled, all Azure AD Graph activity logs will be ingested into the selected Log Analytics workspace.


Logging and detections

The logs are stored in the AADGraphActivityLogs table within Log Analytics. Microsoft has published official documentation that includes the table schema and serves as a useful reference:

Azure Monitor Logs reference – AADGraphActivityLogs | Microsoft Learn

At a high level, this table is similar to MicrosoftGraphActivityLogs, although there are some notable differences. For example, IpAddress in AADGraphActivityLogs corresponds to CallerIpAddress in MicrosoftGraphActivityLogs.

For now, I will not go into advanced detail on the detection capabilities and queries. For a deeper understanding of the schema and practical detection examples, refer to the blogs listed below, which provide detailed explanations and sample queries.

Another good read by Truls on infernux.no: AADGraphActivityLogs in Microsoft Sentinel

And for detections, check the blog created by Fabian Bader. Now You See Me: AADGraphActivityLogs – Cloudbrothers


How to generate some sample data?

To generate data in the old API, I use AADInternals and ROADtools. You can use AADInternals to generate a request and then validate that it appears in the AADGraphActivityLogs table.

For example:

# Ensure Azure CLI is available and logged in:
# az login

# Install AADInternals if needed
if (-not (Get-Module -ListAvailable -Name AADInternals)) {
    Install-Module AADInternals -Scope CurrentUser -Force
}

# Import module
Import-Module AADInternals -Force

# Get module path
$modulePath = (Get-Module AADInternals -ListAvailable |
    Sort-Object Version -Descending |
    Select-Object -First 1).ModuleBase

Write-Host "AADInternals path: $modulePath" -ForegroundColor Cyan

# Load required dependencies
$requiredFiles = @(
    "CommonUtils.ps1",
    "AccessToken_utils.ps1",
    "AccessToken.ps1",
    "GraphAPI_utils.ps1",
    "GraphAPI.ps1"
)

foreach ($file in $requiredFiles) {
    $fullPath = Join-Path $modulePath $file

    if (Test-Path $fullPath) {
        . $fullPath
        Write-Host "Loaded $file" -ForegroundColor Green
    }
    else {
        Write-Warning "$file not found"
    }
}

# Verify required functions exist
$requiredFunctions = @(
    "Read-Accesstoken",
    "Is-AccessTokenExpired",
    "Get-TenantDetails",
    "Get-AADUsers",
    "Get-Devices"
)

foreach ($func in $requiredFunctions) {
    if (-not (Get-Command $func -ErrorAction SilentlyContinue)) {
        throw "Required function '$func' was not loaded."
    }
}

# Get Azure AD Graph token
$token = az account get-access-token `
    --resource https://graph.windows.net `
    --query accessToken `
    -o tsv

if ([string]::IsNullOrWhiteSpace($token)) {
    throw "Failed to obtain access token from Azure CLI."
}

Write-Host "Token acquired. Length: $($token.Length)" -ForegroundColor Green

# Tenant Details
Write-Host "`n=== Tenant Details ===" -ForegroundColor Cyan
Get-TenantDetails -AccessToken $token

# Users
Write-Host "`n=== First 10 Users ===" -ForegroundColor Cyan
Get-AADUsers -AccessToken $token |
    Select-Object -First 10 |
    Format-Table DisplayName,UserPrincipalName -AutoSize

# Devices
Write-Host "`n=== First 10 Devices ===" -ForegroundColor Cyan
Get-Devices -AccessToken $token |
    Select-Object -First 10 |
    Format-Table DisplayName,ObjectId -AutoSize

This command uses the legacy Azure AD Graph endpoint and should generate an entry in AADGraphActivityLogs if logging is enabled. The PowerShell script receives a couple of data files, including AADusers/ Devices and tenant details.

AADGraphActivityLogs
| where TimeGenerated > ago(1h)
| where UserAgent has "AADInternals"

More detailed explanations of how to run advanced commands with AADInternals or ROADtools can be found in other blogs. Above is just an example of how to generate logs


Data lake

When cost optimization is a priority, it is possible to route the AADGraphActivityLogs table directly to the Data Lake storage tier instead of ingesting all data into Log Analytics. This approach ensures that all Graph activity logs are retained in a cost-effective storage layer while avoiding the high ingestion and retention costs associated with large log volumes.

To maintain detection visibility, organizations can leverage KQL jobs or Summary Rules to process the raw data and ingest only the relevant events, aggregates, or security findings into Log Analytics. For example, to filter on the user agent to split suspicious activity from the normal graph API activity.


Conclusion

The introduction of AADGraphActivityLogs closes a long-standing visibility gap in Entra ID monitoring. While Azure AD Graph is considered legacy technology, it remains widely used by older applications, automation workflows, and security assessment tools.

Defenders can now identify these dependencies, improve migration efforts, and detect reconnaissance activity that previously operated with limited visibility. Organizations relying on MicrosoftGraphActivityLogs should review their diagnostic settings and consider enabling AzureADGraphActivityLogs to gain a more complete picture of Graph API activity across their tenant.