Microsoft Graph API Integration
4 minute read
Overview
Microsoft Graph is the gateway to data and intelligence in Microsoft 365, providing unified access to Azure Active Directory, Office 365, Enterprise Mobility, and Windows services. The Edge Delta HTTP Pull source can retrieve audit logs, sign-in data, and other telemetry using Microsoft Graph’s OData query capabilities and JSON-based pagination.
Authentication
Microsoft Graph requires OAuth 2.0 bearer tokens. You’ll need to register an application in Azure AD and obtain an access token.
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
Azure AD Sign-In Logs
Monitor authentication events with time-based filtering and automatic pagination:
nodes:
- name: azure_ad_signins
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/auditLogs/signIns
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
# OData query parameters
parameter_expressions:
$top: "100"
$filter: Concat(["createdDateTime ge ", FormatTime(Now() - Duration("1h"), "%Y-%m-%dT%H:%M:%SZ")], "")
$select: "id,createdDateTime,userPrincipalName,status,ipAddress,location,deviceDetail"
# JSON-based pagination for OData
pagination:
url_json_path: "$['@odata.nextLink']"
max_parallel_requests: 3
pull_interval: 5m
The @odata.nextLink
field contains the URL for the next page of results. The bracket notation $['@odata.nextLink']
is required due to the @ character.
Audit Logs
Retrieve directory audit logs for compliance and monitoring:
nodes:
- name: azure_audit_logs
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/auditLogs/directoryAudits
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameter_expressions:
$top: "100"
$filter: Concat(["activityDateTime ge ", FormatTime(Now() - Duration("24h"), "%Y-%m-%dT%H:%M:%SZ")], "")
pagination:
url_json_path: "$['@odata.nextLink']"
pull_interval: 15m
User Activity Reports
Monitor user activity across Microsoft 365 services:
nodes:
- name: user_activity_reports
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/reports/getEmailActivityUserCounts(period='D7')
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameters:
- name: $format
value: "application/json"
pull_interval: 1h
Security Alerts
Retrieve security alerts from Microsoft Defender:
nodes:
- name: security_alerts
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/security/alerts
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameter_expressions:
$top: "50"
$filter: Concat(["createdDateTime ge ", FormatTime(Now() - Duration("6h"), "%Y-%m-%dT%H:%M:%SZ")], "")
$orderby: "createdDateTime desc"
pagination:
url_json_path: "$['@odata.nextLink']"
pull_interval: 10m
Teams Activity
Monitor Microsoft Teams usage and activity:
nodes:
- name: teams_activity
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/reports/getTeamsUserActivityCounts(period='D7')
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameters:
- name: $format
value: "application/json"
pull_interval: 1h
Mailbox Statistics
Track Exchange Online mailbox usage:
nodes:
- name: mailbox_usage
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/reports/getMailboxUsageDetail(period='D7')
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameters:
- name: $format
value: "application/json"
pagination:
url_json_path: "$['@odata.nextLink']"
pull_interval: 6h
SharePoint Activity
Monitor SharePoint and OneDrive activity:
nodes:
- name: sharepoint_activity
type: http_pull_input
endpoint: https://graph.microsoft.com/v1.0/reports/getSharePointActivityPages(period='D7')
method: GET
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
parameters:
- name: $format
value: "application/json"
pull_interval: 1h
OData Query Parameters
Microsoft Graph uses OData v4 query parameters:
Parameter | Description | Example |
---|---|---|
$filter |
Filter results | createdDateTime ge 2024-01-01T00:00:00Z |
$select |
Select specific fields | id,displayName,mail |
$orderby |
Sort results | createdDateTime desc |
$top |
Limit results per page | 100 |
$skip |
Skip results | 50 |
$count |
Include total count | true |
$search |
Search across fields | "displayName:admin" |
Filter Examples
Common filter patterns for Microsoft Graph:
# Date filtering
$filter: Concat(["createdDateTime ge ", FormatTime(Now() - Duration("24h"), "%Y-%m-%dT%H:%M:%SZ")], "")
# Multiple conditions
$filter: "status/errorCode eq 0 and location/countryOrRegion eq 'US'"
# String contains
$filter: "startswith(userPrincipalName, 'admin')"
# In operator
$filter: "userType in ('Member', 'Guest')"
Authentication Setup
- Register an application in Azure AD
- Grant required API permissions
- Obtain an access token
Required permissions vary by endpoint:
- Sign-in logs:
AuditLog.Read.All
- Directory audits:
Directory.Read.All
- Security alerts:
SecurityEvents.Read.All
- Reports:
Reports.Read.All
Environment Variables
# OAuth 2.0 Bearer Token
export GRAPH_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGc..."
# Or use client credentials flow
export TENANT_ID="your-tenant-id"
export CLIENT_ID="your-client-id"
export CLIENT_SECRET="your-client-secret"
Token Refresh
For long-running operations, implement token refresh logic:
# Use a script to refresh tokens periodically
header_expressions:
Authorization: Concat(["Bearer ", EDXEnv("GRAPH_TOKEN", "")], "")
# Token should be refreshed externally and environment variable updated
Rate Limiting
Microsoft Graph implements throttling:
- Service-specific limits apply
- 429 responses include Retry-After header
Handle rate limiting:
retry_http_code:
- 429 # Too Many Requests
- 503 # Service Unavailable
pagination:
max_parallel_requests: 2 # Conservative for throttling
Troubleshooting
401 Unauthorized:
- Token expired - refresh access token
- Insufficient permissions - check API permissions
403 Forbidden:
- License requirements not met
- Conditional access policies blocking access
400 Bad Request:
- Invalid OData query syntax
- Unsupported filter operations
Empty results:
- Check time range in filter
- Verify data exists for the period
- Some reports require 48-hour data availability
Pagination Patterns
Microsoft Graph uses different pagination patterns:
- OData nextLink (most common):
pagination:
url_json_path: "$['@odata.nextLink']"
- Skip token (some endpoints):
pagination:
url_json_path: "$['@odata.nextLink']"
# Automatically handles $skiptoken parameter
- No pagination (single-page results):
# Omit pagination configuration