Microsoft Graph API Integration

Configure HTTP Pull to retrieve data from Microsoft Graph API endpoints including Azure AD logs, user activity, and Office 365 telemetry.

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

  1. Register an application in Azure AD
  2. Grant required API permissions
  3. 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:

  1. OData nextLink (most common):
pagination:
  url_json_path: "$['@odata.nextLink']"
  1. Skip token (some endpoints):
pagination:
  url_json_path: "$['@odata.nextLink']"
  # Automatically handles $skiptoken parameter
  1. No pagination (single-page results):
# Omit pagination configuration