Entra ID (AzureAD) Audit via Graph API
The Azure Directory Audit template polls the Microsoft Entra ID (formerly Azure AD) directory audit and sign-in logs from Microsoft Graph: who changed users, groups, roles and application grants in the directory, and who signed in from where.
You never open the Microsoft portal: you enter an administrator's email address, and Microsoft asks that administrator to approve FluencyAzureADAudit, an application Fluency already operates, so there is no app registration and no client secret. The person who finishes the setup, a Global Administrator or Privileged Role Administrator, may not be you, and until they approve, the application reports Running and collects nothing.
The setup has two halves, and the Fluency half comes first:
- In Fluency: install the Azure Directory Audit template with an administrator's email address. This sends the approval request.
- In Microsoft: that administrator reviews the permissions and accepts.
| Template | How the logs leave Entra ID | What your tenant grants | Guide |
|---|---|---|---|
| Azure Directory Audit (this page) | Fluency polls Microsoft Graph | Tenant-wide AuditLog.Read.All and Directory.Read.All to a Fluency application | This page |
| Azure Directory Audit (Event Hub) | A diagnostic setting pushes them into an event hub in your Azure subscription | A Listen-only connection string to that one event hub | Entra ID (AzureAD) Audit via Event Hubs |
Both collect essentially the same records and file them in the same shape in the same index, so run one or the other; Graph API or Event Hubs sets out the differences.
What arrives
| Stream | What it holds | Lands in |
|---|---|---|
| Directory audit | Directory changes: users and groups created or modified, role assignments, application and consent grants, password resets, PIM activity. | The MSEntra and AzureAuditLogs indexes |
| Sign-ins | Interactive sign-ins, with client IP, device, application, Conditional Access result and risk state. | The MSEntra and AzureSigninLogs indexes |
Sign-ins need Microsoft Entra ID P1 or P2; see Before you begin. Fluency reads only what Entra still holds, so collection that stops for longer than Entra's retention (seven days on Free, 30 on P1 or P2) loses data for good; see Retention decides how long an outage can last. Non-interactive, service principal and managed identity sign-ins are not collected; the Event Hub route collects them, as Graph API or Event Hubs shows.
Endpoints and permissions, the indexes, the record shape and the legacy AzureAudit index name are in Data reference.
Before you begin
A Global Administrator or Privileged Role Administrator to approve the request. Microsoft's rule is:
Privileged Role Administrator, for granting consent for apps requesting any permission, for any API.
Cloud Application Administrator, AI Administrator, or Application Administrator, for granting consent for apps requesting any permission for any API, except Microsoft Graph app roles (application permissions).
This application requests AuditLog.Read.All as a Microsoft Graph application permission, so it falls in the exception: Cloud Application Administrator and Application Administrator are not sufficient.
Microsoft Entra ID P1 or P2, for sign-ins only. The directory audit works on every tier, including Free. Without P1 or P2, the sign-in endpoint returns
Authentication_RequestFromNonPremiumTenantOrB2CTenant:
Neither tenant is B2C or tenant doesn't have premium license
and the rest of the integration is unaffected.
An email address that will get the consent link to the approver. It does not have to be the administrator's own; see the note under Install the Application.
Access to the Fluency portal with permission to install applications.
Part 1: Fluency
Install the Application
- v2 interface
- Classic v1 interface
In the navigation rail, open Applications and click Install Application, then choose Azure Directory Audit from the Office Software (SaaS) and IAM category of the Application Catalog.
Go to Platform → Applications → Install Application From Template and choose Azure Directory Audit from the Office Software (SaaS) and IAM category.
| Parameter | Notes |
|---|---|
| Enable Admin Consent Mode? | Checkbox, ticked by default. Leave it ticked for the consent route. Unticking it changes the form; see If your tenant will not allow the consent route. |
| admin email address | Where the consent link is sent. Any valid address (see the note below). |
| datalake | Pre-filled managed. |
| datalake index name | Pre-filled MSEntra, the index of every record; older deployments use the legacy name AzureAudit. Keep it: the Entra ID search facets are set on MSEntra by name. Two applications writing to the same index name in the same lake will collide, and the second one aborts. |
Office365-Audit collects this directory audit and these sign-ins too, from the same Graph endpoints, and its install creates the same table indexes. Both also write the directory audit to an index that defaults to MSEntra, this template's datalake index name and Office365-Audit's datalake index name for Entra ID (AzureAudit) events, as does Entra ID (AzureAD) Audit via Event Hubs, and two applications writing to the same index name in the same lake will collide, and the second one aborts. Run one or the other, not both.
The admin email address can be any valid email address. It is used only to deliver the consent link and plays no part in authentication. Whoever opens the link signs in to Microsoft with the actual administrator account, which can be a different address entirely. The Global Administrator or Privileged Role Administrator requirement applies to the account that signs in, not to the address the link was sent to.
- v2 interface
- Classic v1 interface
datalake and datalake index name sit in the collapsed Advanced configuration section below Configuration; click its heading to reach them.

While Enable Admin Consent Mode? is ticked, Dry run is greyed out: there is no credential of yours for it to check. Click Install Application. The Applications page opens with the notice Default is launching. and lists the new application with its status badge.
datalake and datalake index name sit in the collapsed Advanced Configurations row below the parameters; expand it to reach them.

Press Install. The application then appears in the Installed Applications view, where its badge reads Running once the pipeline is up.
The badge reflects the pipeline, not the consent. Until the administrator approves in Microsoft, this application has nothing to read, and it looks identical to one that is collecting normally. The check that answers the question is on the Microsoft side; see Confirm it is running.
If your tenant will not allow the consent route
If your organisation blocks consent to third-party applications, untick Enable Admin Consent Mode; the form replaces the email field with Azure Tenant ID, Azure ClientID and Azure ClientSecret, for an app registration you create and hold yourself. Build it as described in Part 1 of the Office 365 Audit page, granting AuditLog.Read.All and Directory.Read.All as Application permissions on Microsoft Graph.
A tenant that blocks third-party consent can also collect the same logs through Entra ID (AzureAD) Audit via Event Hubs, which needs no application in the tenant at all.
Part 2: Microsoft
This half is performed by the administrator who opens the consent link.
Review the request and accept
Opening the link takes the administrator to login.microsoftonline.com, where they sign in with their administrator account and are shown the permission request. If nothing arrives, check spam quarantine first; reinstalling does not change how the request is delivered.

| Consent screen wording | Permission | What it buys |
|---|---|---|
| Sign in and read user profile | User.Read (delegated) | Identifies the signing-in administrator during the consent itself. Not used for collection. |
| Read all audit log data | AuditLog.Read.All | The directory audit and sign-in endpoints. |
| Read directory data | Directory.Read.All | Resolves the object GUIDs in audit records to names, and lets the sign-in endpoint read the tenant's licensing. |
Three checks before accepting:
- The application is
FluencyAzureADAuditand the publisher is Fluency Corp. If either is different, stop. - The list is exactly these three. A consent screen asking for more is not this integration.
- The screen says Review for your organization; that is the tenant-wide grant.
Click Accept. If the administrator clicks Cancel, Microsoft returns AADSTS65004: The resource owner or authorization server denied the request., no grant is created, and nothing on the Fluency side reports it.
Once accepted, the grant lives on the tenant rather than on the administrator who approved it. It does not expire, it survives the approver leaving, and it can be revoked by anyone with the role from Enterprise applications without Fluency being told.
Confirm it is running
In the Microsoft Entra admin center, go to Entra ID → Enterprise apps → All applications and search for FluencyAzureADAudit. If consent was granted, the application is there; if it is not, the request was never accepted.

Security → Permissions → Admin consent shows exactly what was granted. Its Type column separates Delegated from Application, which matters because Read directory data is worded identically for both.
Then check that events are landing: search the MSEntra index (managed-MSEntra in the Data lake index drop-down) for @eventType:AuditLogs, or, on an older deployment, the AzureAudit index. See Confirm data is arriving. The directory audit only records changes, so on a quiet tenant make a harmless change in Entra (create a group, then delete it) and search for it a few minutes later.
Graph API or Event Hubs
Both templates collect the Entra directory audit and interactive sign-ins and file them identically: the same shape in MSEntra, and the same five table indexes (AzureAuditLogs, AzureSigninLogs and the three AAD…SignInLogs). The same search facets and Entra ID detections work on either. Running both stores every record twice and raises every Entra ID detection twice, so run one or the other. They differ in what each asks of your tenant and in a few categories at the edges:
| Azure Directory Audit (Graph API) | Azure Directory Audit (Event Hub) | |
|---|---|---|
| Who sets it up | A Global Administrator or Privileged Role Administrator, approving a consent request | Contributor on an Azure subscription, then a Security Administrator for the diagnostic setting |
| What Fluency holds | A tenant-wide Graph grant | A Listen-only connection string to one event hub |
| Entra categories | Directory audit and interactive sign-ins | The same, plus non-interactive, service principal and managed identity sign-ins and provisioning; not the risk categories |
@source on each record | AzureAudit | AzureEventHub |
| How long collection can stop without loss | Entra's retention: seven days on Free, 30 on P1 or P2 | The hub's retention: one day on Basic, up to seven on Standard |
| Azure cost | None | The Event Hubs namespace, billed hourly |
The Graph API route has nothing to build or pay for in Azure and rides out a longer outage on a P1 or P2 tenant. The Event Hub route puts no application in your directory and adds the sign-in categories this template does not collect; with non-interactive sign-ins, the stolen-session detections also see the token refreshes a replayed session makes.
Maintenance
There is no credential to rotate
No secret expires on the consent route. What can break the integration is someone revoking the consent, so the maintenance task is review rather than rotation.
Reviewing and revoking the grant
From Entra ID → Enterprise apps → All applications → FluencyAzureADAudit → Permissions → Admin consent, use the ... control on a permission row and select Revoke permission.

- Nothing tells Fluency. Collection stops and the application keeps reporting Running. On a Free tenant that silence costs a week of data before anyone is likely to notice.
- Revoking does not stop the application being re-consented. Microsoft notes that "Revoking the current granted permission doesn't stop users from re-consenting to the application's requested permissions." To block it permanently, delete the enterprise application or restrict consent at the tenant level.
Removing the integration
Uninstall the application in Fluency first, with the Uninstall button at the top right of its details page (v1: the red Uninstall button at the foot of its details panel on Platform → Applications), then delete the enterprise application in Entra ID (Properties → Delete) or revoke its permissions as above.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| The application shows Error (v1: Aborted) immediately after install | An index name is already taken: usually MSEntra from Office365-Audit or Entra ID (AzureAD) Audit via Event Hubs (AzureAudit on an older deployment) | The error message in the application's details names the index. Either application already collects this feed; keep one of the two. |
| The administrator sees Need admin approval rather than a consent screen | AADSTS90094: the account cannot consent to Microsoft Graph application permissions | Have a Global Administrator or Privileged Role Administrator open the same link. |
Consent fails with AADSTS65004 | The administrator selected Cancel | Send the request again. No grant was created. |
| The administrator never received anything | Wrong address, or the message was quarantined | Check the address on the install form, then spam quarantine. |
| Running, but the index is empty and has always been empty | Consent was never granted | Search Enterprise applications for FluencyAzureADAudit. If it is absent, the request was not accepted; resend it. |
| Running, consent is granted, index still empty | The tenant may simply be quiet | Make a harmless change in Entra and search for it. |
| Directory audit records arrive, sign-in records never do | The tenant has no Entra ID P1 or P2 licence | Expected on Free. Neither tenant is B2C or tenant doesn't have premium license confirms it. |
Sign-in records arrive but appliedConditionalAccessPolicies is empty | Policy.Read.All is not granted | The consent route does not request it. On the client-secret route, add it to your registration. |
| The premium-licence error appears intermittently rather than always | Directory.Read.All missing or uncached | Microsoft notes that permission is what retrieves tenant licensing information. Confirm both permissions are on the Admin consent tab. |
| Collection worked, then stopped, with no change on the Fluency side | The grant was revoked, or the application was deleted | Check Enterprise applications → Permissions → Admin consent. Re-consent if it is gone. |
| A gap in the data that will not backfill | The events aged out of Entra | Unrecoverable. Seven days on Free, 30 on P1 or P2. |
Data reference
What the two streams look like once they land, for searches and detection rules written against them.
Streams, endpoints and permissions
| Stream | Endpoint | Permission | Contents |
|---|---|---|---|
| Directory audit | GET /v1.0/auditLogs/directoryAudits | AuditLog.Read.All | Directory changes: users and groups created or modified, role assignments, application and consent grants, password resets, PIM activity. |
| Sign-ins | GET /v1.0/auditLogs/signIns | AuditLog.Read.All | Interactive sign-ins with client IP, device, application, Conditional Access result and risk state. Requires Entra ID P1 or P2; see Before you begin. |
Where the records land
Both streams land in three indexes:
| Index | Contents | Named by |
|---|---|---|
MSEntra | Every record, both streams, in the shape described below. | The form's datalake index name |
AzureAuditLogs | The directory audit, in the AzureAuditLogs schema. | The template |
AzureSigninLogs | The sign-ins, in the AzureSigninLogs schema. | The template |
The install also creates AADNonInteractiveUserSignInLogs, AADServicePrincipalSignInLogs and AADManagedIdentitySignInLogs, the tables for the other sign-in types, which stay empty: this template collects interactive sign-ins only. The five table indexes are created by the install and are not exposed as parameters, so they cannot be renamed to dodge a collision.
AzureAudit is the legacy name of the form's index: older deployments write every record to AzureAudit rather than MSEntra, and keep doing so.
The record shape
Each record in MSEntra has the shape a Microsoft Entra diagnostic setting exports: Graph's sign-in or audit object, unchanged, under @azure.properties, inside the Azure Monitor envelope (time, category, operationName, resultType and the rest). @eventType holds the category (AuditLogs for the directory audit, SignInLogs for an interactive sign-in) and @source is AzureAudit. A few envelope values that Graph does not return are absent.
That is the shape the Event Hub template writes to the same index, so the Default-EntraID_AuditLogs and Default-EntraID_SignIn search facets and the Entra ID detection rules work the same on records from either route.
Retention decides how long an outage can last
| Report | Entra ID Free | Entra ID P1 | Entra ID P2 |
|---|---|---|---|
| Audit logs | Seven days | 30 days | 30 days |
| Sign-ins | Seven days | 30 days | 30 days |
This template reads what Entra still holds, so Entra's retention is how long collection can stop before data is lost for good. Seven days on a Free tenant is the number that catches people: an outage over a long weekend, unnoticed until Tuesday, is close to the limit. Microsoft is explicit that there is no recovery path: "Log retention changes aren't retroactive", and "Data that has already expired can't be recovered unless it was previously archived." Upgrading the licence afterwards does not help either: "When you switch from a free to a premium version, you can only see up to 7 days of data."
Under the hood
Engineering reference: the consent flow, the Graph endpoints and the install
How the consent route authenticates
The application Fluency operates is registered as multi-tenant in Fluency's own directory. Approval goes through Microsoft's admin consent endpoint:
https://login.microsoftonline.com/{tenant}/v2.0/adminconsent
?client_id={fluency-client-id}
&scope=https://graph.microsoft.com/.default
&redirect_uri={fluency-callback}
&state={opaque}
Approval produces a redirect carrying admin_consent=True and the tenant GUID, which is why the form never asks for a tenant ID.
Collection then uses the client credentials grant against https://graph.microsoft.com/.default. Application permissions produce an appRoleAssignment on the service principal, and delegated permissions consented tenant-wide produce an oauth2PermissionGrant with consentType: AllPrincipals. Neither references the approving user's account, which is why the grant outlives them.
The Graph endpoints
Both streams are ordinary Graph collections, polled with a timestamp filter and paginated through @odata.nextLink:
GET https://graph.microsoft.com/v1.0/auditLogs/directoryAudits
GET https://graph.microsoft.com/v1.0/auditLogs/signIns
directoryAudits filters on activityDateTime; signIns filters on createdDateTime. appliedConditionalAccessPolicies is populated on sign-in records only when the caller also holds Policy.Read.All, which this application does not request.
What the install creates
Two pipes run on the application's router. The first, AzureAudit_Transform, rewrites each sign-in into the schema of the table for its sign-in type (AzureSigninLogs for an interactive one) and each directory audit record into the AzureAuditLogs schema, writes it to the index of the same name, and passes the original record on. The second, AzureAudit_EntraAdjustments, wraps a copy of each record in the Azure Monitor envelope, sets @eventType to its category (a sign-in's from its signInEventTypes) and writes it to the index named on the form, then hands it to the Entra ID detection rules for that category. The application's Actions list records one line per object created; addDatalakeIndex entries create the indexes in the managed lake as a side effect of the install, which is why a name that already exists aborts the whole application.
References
Microsoft
- Microsoft Entra audit logs API overview: the endpoints and their shapes
- List directoryAudits and List signIns
- Microsoft Entra data retention: seven days on Free, 30 on P1/P2
- Grant tenant-wide admin consent: which roles can approve
- Review permissions granted to enterprise applications: reviewing and revoking
- Admin consent on the Microsoft identity platform: the endpoint and its error responses
Fluency
- Entra ID (AzureAD) Audit via Event Hubs: the same Entra ID logs, streamed through an event hub instead of polled from Graph
- Office 365 Audit: this feed plus the unified audit log and the directory resources, on a client secret
- Azure Directory Audit install form: the template's fields, in both consent modes (v1: Install Application From Template)
- Confirm data is arriving
- Microsoft integrations: the rest of this category