Skip to content

Audit Logs

The Microsoft 365 Unified Audit Log captures activity across Exchange Online, SharePoint Online, OneDrive, Teams, Entra ID, and other services.

Purview portal → Audit


Enable Audit Logging

Audit logging should be on by default for new tenants, but verify:

Connect-ExchangeOnline -UserPrincipalName admin@domain.com

# Check if audit is enabled
Get-AdminAuditLogConfig | Select-Object UnifiedAuditLogIngestionEnabled

# Enable if not already on
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true

Audit Log Retention

Default retention varies by licence:

Licence Default retention
Microsoft 365 E3 / Business Premium 90 days
Microsoft 365 E5 / Advanced Audit 1 year
Advanced Audit add-on Up to 10 years (with additional licence)

Extended retention policy (Advanced Audit — E5)

Purview portal → Audit → Audit retention policies → Create audit retention policy

Setting Value
Policy name 1 Year — All Users All Activities
Record type All
Duration 1 year
Priority 1
Users All users

Searching the Audit Log

Via the portal

Purview portal → Audit → New search

Field Description
Date range Up to 90 days per search (E3) or 1 year (E5)
Activities Filter by specific activity types
Users Search for specific user(s)
File/folder Filter by resource name
IP address Filter by source IP
Activity category What to look for
Azure AD sign-in UserLoggedIn — failed logins, logins from new locations
Exchange SendAs, HardDelete, MailboxLogin
SharePoint/OneDrive FileDownloaded, FileSyncDownloadedFull, SharingInvitationCreated
Teams MessageSent, TeamCreated, MemberAdded
DLP DLPRuleMatch — policy matches
Azure AD Add member to role, Delete user, Reset user password
Power Apps / Flow Suspicious automation activity

Searching via PowerShell

Connect-ExchangeOnline -UserPrincipalName admin@domain.com

# Search for all activity by a specific user in the last 7 days
$start = (Get-Date).AddDays(-7).ToString("MM/dd/yyyy HH:mm:ss")
$end = (Get-Date).ToString("MM/dd/yyyy HH:mm:ss")

Search-UnifiedAuditLog -StartDate $start -EndDate $end `
    -UserIds "user@domain.com" -ResultSize 1000 |
    Select-Object CreationDate, UserIds, Operations, AuditData |
    Sort-Object CreationDate -Descending

# Search for all failed logins in the last 24 hours
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date) `
    -Operations "UserLoginFailed" -ResultSize 1000 |
    ForEach-Object {
        $data = $_.AuditData | ConvertFrom-Json
        [PSCustomObject]@{
            Time      = $_.CreationDate
            User      = $data.UserId
            IP        = $data.ClientIP
            UserAgent = $data.ExtendedProperties | Where-Object { $_.Name -eq "UserAgent" } | Select-Object -ExpandProperty Value
        }
    }

# Search for external file sharing events
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
    -Operations "SharingInvitationCreated","AnonymousLinkCreated" -ResultSize 2000 |
    ForEach-Object {
        $data = $_.AuditData | ConvertFrom-Json
        [PSCustomObject]@{
            Time      = $_.CreationDate
            User      = $data.UserId
            TargetEmail = $data.TargetUserOrGroupName
            File      = $data.ObjectId
        }
    } | Where-Object { $_.TargetEmail -notlike "*@yourdomain.com" }

# Search for admin role changes
Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date) `
    -Operations "Add member to role","Remove member from role" -ResultSize 500 |
    ForEach-Object {
        $data = $_.AuditData | ConvertFrom-Json
        [PSCustomObject]@{
            Time      = $_.CreationDate
            Actor     = $data.UserId
            Target    = ($data.ModifiedProperties | Where-Object { $_.Name -eq "Role.WellKnownObjectName" }).NewValue
            Action    = $_.Operations
        }
    }

Alerting on Audit Events

Purview portal → Audit → Alert policies (or via Microsoft Defender portal)

Recommended alert policies:

Alert Trigger Severity
Admin privilege escalation Add member to Global Admin role High
Mass file download User downloads >500 files in 1 hour High
Forwarding rule created New inbox forwarding rule to external address High
Multiple failed logins >10 failed logins for a single user Medium
Anonymous sharing link created AnonymousLinkCreated Medium
DLP policy match DLPRuleMatch on high-severity policy High
Malware detected in email A malware campaign was detected High

Exporting Audit Logs

Export logs to CSV for long-term storage or SIEM ingestion:

# Export all audit logs for a date range to CSV
$results = Search-UnifiedAuditLog -StartDate "2025-01-01" -EndDate "2025-01-31" `
    -ResultSize 5000

$results | Select-Object CreationDate, UserIds, Operations, `
    @{N="AuditDataParsed";E={ $_.AuditData }} |
    Export-Csv -Path ".\AuditLog-Jan2025.csv" -NoTypeInformation

# For large exports, loop through pages
$sessionId = [Guid]::NewGuid().ToString()
$allResults = @()
do {
    $batch = Search-UnifiedAuditLog -StartDate "2025-01-01" -EndDate "2025-01-31" `
        -ResultSize 5000 -SessionId $sessionId -SessionCommand ReturnLargeSet
    $allResults += $batch
} while ($batch.Count -eq 5000)

$allResults | Export-Csv -Path ".\AuditLog-Full.csv" -NoTypeInformation

SIEM integration

For continuous audit log ingestion into a SIEM (Splunk, Microsoft Sentinel, etc.), use the Office 365 Management Activity API or the built-in Microsoft Sentinel — Office 365 connector.