Introduction
Exchange On-premises allows you to activate audit on mailboxes usages. The audit can be at the level of changes made by administrators (Admin), at the level of delegate access (Delegate) and at the level of the mailbox owner (Owner). Exchange Online offers the same type of auditing services, this auditing is enabled by default with a 90-days retention period. To have more than 90 days additional licenses are necessary.
Access to audit logs can be done in several ways:
- Access through the Unified Audit Log (UAL) with the “Defender 365 Portal” tool or powershell
- Access through “Management Activity” API (API used by SIEMs)
Verify Exchange Online Audit configuration
Exchange Online mailbox auditing can be verified at the Exchange Online organization level with the powershell command Get-OrganizationConfig | fl AuditDisabled
PowerShell command.

When auditing is enabled it will be “by default” on all mailboxes: user mailsboxes and shared mailboxes.
A bypass on some mailboxes can be configured using the following powershell command:
Set-MailboxAuditBypassAssociation -Identity <account> -AuditByPassEnabled $ true
The Get-MailboxAuditBypassAssociation
command allows you to check the status of the audit bypass.

Mailbox auditing is supported on the following mailbox types: https://docs.microsoft.com/en-us/microsoft-365/compliance/enable-mailbox-auditing?view=o365-worldwide

To check the status of this unified audit system, use the Get-AdminAuditLogConfig
command.

Note: To activate the unified log feature for a mailbox without license, it is necessary for each mailbox to re-launch a command “set-mailbox -AuditEnabled $true
“. See https://docs.microsoft.com/en-us/microsoft-365/compliance/enable-mailbox-auditing?view=o365-worldwide#more-information.
Auditing is enabled by default on each mailbox and the “DefaultAuditSet” property of a mailbox allows you to check which type of access the audit is enabled. By default this property is set to “Admin, Delegate, Owner”.
In this case, the list of audited actions is defined by Microsoft and the “AuditAdmin”, “AuditDelegate” and “AuditOwner” properties are managed by Microsoft.

If any of these three properties is updated to add or delete action type, the management of these properties by Microsoft will be automatically disabled.

It is then possible to reset the default values managed by Microsoft by setting the “DefaultAuditSet” property.

Access UAL with DEFENDER 365 portal and PowerShell
The “Compliance Center” and “Microsoft 365 Defender” tools provide access to audit logs, but more generally.
It is then possible to search in this unified audit log (UAL) via the “Audit” menu of the “Microsoft 365 Defender” portal.

This UAL can also be searched using the powershell command Search-UnifiedAuditLog
.

Here a complete powershell function that permits to request UAL with criteria and pagination management.
Function Get-UALEvents() {
###########################################################
# Sample
# $Events = Get-UALEvents -StartDate (get-date('20/03/2024')) -EndDate (get-date("21/03/2024")) -RecordType ExchangeItem -Operations "AddFolderPermissions,RemoveFolderPermissions,ModifyFolderPermissions"
# $Events = Get-UALEvents -StartDate (get-date).addhours(-2) -EndDate (get-date) -RecordType ExchangeItem -Operations "AddFolderPermissions,RemoveFolderPermissions,ModifyFolderPermissions"
# $Events = Get-UALEvents -StartDate (get-date).addhours(-2) -EndDate (get-date) -RecordType ExchangeItem -Userids xxx@yyy.com
# $Events = Get-UALEvents -StartDate (get-date "23/05/2024 10:00") -EndDate (get-date "23/05/2024 10:00") -Userids xxx@yyy.com -RecordType ExchangeAdmin
# $Events = Get-UALEvents -StartDate (get-date "20/05/2024 09:00") -EndDate (get-date "29/05/2024 09:00") -Userids lionel.traverse@externe.bnpparibas.com -Operations "AddFolderPermissions,ModifyFolderPermissions"
###########################################################
param(
[datetime]$StartDate,
[datetime]$EndDate,
[String]$RecordType = "ExchangeItem",
[String]$Operations = "*",
[String]$Userids = "*"
)
$StartRequest = Get-date
$myResult = $null
$myPage = $null
$mySession = (Get-Random).tostring()
$myLoop = 0
write-host "===> Start collect"
while ($true) {
$myLoop += 1
if ( $myLoop -ge 500 ) { Break }
$myPage = Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -ResultSize 100 -SessionId $mySession -SessionCommand ReturnLargeSet -RecordType $RecordType -Userids $Userids -Operations $Operations
Write-Host " Page $($myLoop) = $($myPage.count) events"
$myResult += $myPage
if ( $myPage.count -lt 100 ) { Break }
}
Write-host "===> Delay =" ([math]::Floor(((get-date) - $StartRequest).TotalSeconds)) "seconds"
Write-host "===> Events =" ($myResult.count)
Return ($myResult | Sort-Object -Property CreationDate)
}
Access UAL with Management API
Exchange Online audits are available through a SIEM, as well as through Microsoft SIEM (Azure Sentinel https://docs.microsoft.com/en-us/rest/api/securityinsights).
SIEM uses the Microsoft Management Activity API (https://docs.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-reference) to subscribe to notifications via WebHook or consume UAL with “read activity” method.
To use this API, you must declare an application in Azure AD with certificate or secret authentication.
Create an app in Entra:

Add API permissions to the application from the “Office 365 Management APIs” catalog:

Add the “ActivityFeed.Read” right and grant admin consent to the right.


Add a secret or a certificate to the APP to permits to authenticate with oAuth2.0.
Request an access token with the scope “https://manage.office.com/.default”. You can use TOKEN365 tool or this powershell code:
# Application parameters
$tenantId = "xxxx"
$clientId = "xxxx"
$clientSecret = "xxxx"
# URL to obtain the OAuth 2.0 token
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
# Obtain an OAuth 2.0 access token with management scope
$body = @{
grant_type = "client_credentials"
scope = "https://manage.office.com/.default"
client_id = $clientId
client_secret = $clientSecret
}
$response = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$accessToken = $response.access_token
$accessToken
After, verify that a subscription already exists for your context (exchange, sharedpoint…) with a GET or the URL https://manage.office.com/api/v1.0/<tenant_id>/activity/feed/subscriptions/list.
You can do this with the access token ($accessToken) and this powershell code (or with POSTMAN).
# Application parameters
# reuse $accessToken
$tenantId = "xxxx"
# Microsoft Management Activity API URL to list subscriptions
$subscriptionsUrl = "https://manage.office.com/api/v1.0/$tenantId/activity/feed/subscriptions/list"
# Headers for the API request
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
try {
# Retrieve the list of subscriptions via the Management Activity API
$response = Invoke-RestMethod -Method Get -Uri $subscriptionsUrl -Headers $headers
# Display the subscription details
Write-Host "Available Subscriptions:"
$response | Format-Table -Property contentType, status, expirationDate
} catch {
Write-Error "An error occurred while retrieving subscriptions: $_"
}

If no subscription exists, you can start one with a POST to the URL https://manage.office.com/api/v1.0/<tenant_id>/activity/feed/subscriptions/start?contentType=<audit_catagorie>. For exchange events, the audit catagory is “Audit.Exchange”.
You can do this with POSTMAN or with a powershell code.
# Application parameters
# reuse $accessToken
$tenantId = "xxxx"
# Microsoft Management Activity API URL to create a subscription
$subscriptionUrl = "https://manage.office.com/api/v1.0/$tenantId/activity/feed/subscriptions/start?contentType=Audit.Exchange"
# Headers for the API request
$headers = @{
"Authorization" = "Bearer $accessToken"
"Accept" = "application/json"
}
try {
# Send a request to create the subscription for Audit.Exchange
$response = Invoke-RestMethod -Method Post -Uri $subscriptionUrl -Headers $headers
# Display the response to confirm the subscription was created
Write-Host "Subscription for Audit.Exchange created successfully."
Write-Host "Response:"
$response | Format-List
} catch {
Write-Error "An error occurred while creating the subscription: $_"
}
When the subscription exists, you can read UAL’s events with the management API and the “read activity” method.
Note : You can also use a webhook to request UAL to push events.
By Lionel TRAVERSE
Microsoft 365 Certified Administrator Expert / Microsoft Certified Trainer