Microsoft Entra ID
Proofroom reads Microsoft Entra ID through Microsoft Graph with an app registration’s application permissions, and files six kinds of evidence. Add it on Integrations → Catalogue → Microsoft Entra ID → Connect.
What each collector shows
| Collector | Kind | Default cadence | What it shows | Suggested controls |
|---|---|---|---|---|
| Users with MFA status | snapshot | quarterly | Every enabled user, whether they are an administrator, whether they are registered for MFA and with which methods, from the authentication methods registration report. Without Entra ID P1 or P2, each user’s registered methods are read instead (slower; administrator status is not shown). | PCI DSS 8.4.2, 8.4.3; SOC 2 CC6.1 |
| Admin and privileged roles | snapshot | quarterly | Who holds each directory role, permanently or for a limited time, and who is eligible through Privileged Identity Management (Entra ID P2). Holders whose account is disabled are flagged. A group holding a role keeps its own row, and each of its users (nested groups included) gets a row naming the group. | PCI DSS 7.2.1, 7.2.2, 7.2.4; SOC 2 CC6.2, CC6.3 |
| Leaver removals | window | monthly | Accounts disabled, deleted or permanently deleted in the window, with the time and who did it, from the directory audit log. When a People directory source is set up, each person who left in the window is matched to the removal of their account by email, with the lag in days. | PCI DSS 8.2.5; SOC 2 CC6.2 |
| Inactive accounts | snapshot | quarterly | Every enabled account (members and guests) with its creation date and last successful sign-in, and those with no successful sign-in in 90 days. Needs Entra ID P1 or P2. | PCI DSS 8.2.6; SOC 2 CC6.2 |
| MFA enforcement | snapshot | quarterly | Whether MFA is required for everyone, and for administrators: security defaults, and each Conditional Access policy with its state, who and which apps it covers, who it leaves out, the conditions that narrow it and any authentication strength it requires. Gaps are named. | PCI DSS 8.4.1, 8.4.2, 8.4.3; SOC 2 CC6.1 |
| Microsoft Secure Score | snapshot | monthly | The tenant’s Secure Score as of the run (points and percent), its change over 30 days, Microsoft’s comparison averages, the improvement actions with points left (largest first) and the score for each day Microsoft keeps (about 90). Each run files a new item, so the evidence keeps the score over time. Needs SecurityEvents.Read.All. | PCI DSS 2.2.1; SOC 2 CC7.1 |
The users-mfa evidence shows registration; the MFA enforcement evidence shows whether MFA is required. Email one-time passcodes serve password reset only, so they are listed but not counted as MFA. Proofroom keeps names, sign-in names, roles, dates and statuses only.
Create the app registration
- In the Microsoft Entra admin center, go to Entra ID → App registrations → New registration. Name it “Proofroom” and register it. Note the Application (client) ID and Directory (tenant) ID.
- Certificates & secrets → Client secrets → New client secret. Copy the secret’s Value; it is shown once.
- API permissions → Add a permission → Microsoft Graph → Application permissions, and add:
- User.Read.All: the users list.
- AuditLog.Read.All: the MFA registration report and the directory audit log.
- RoleManagement.Read.Directory: role assignments and, with P2, Privileged Identity Management.
- GroupMember.Read.All: the users in groups that hold an admin role, and group names in Conditional Access policies.
- Policy.Read.All: security defaults, Conditional Access policies and the authentication strengths they require.
- SecurityEvents.Read.All: Microsoft Secure Score (
GET /security/secureScoresandGET /security/secureScoreControlProfiles; Microsoft lists it as the least privileged permission for both). Read only: Proofroom never changes an improvement action’s state. - UserAuthenticationMethod.Read.All: only if the tenant has no Entra ID P1 or P2 (the per-user fallback).
- Application.Read.All (optional): when the client secret expires, and app names in Conditional Access policies. Without it the integration page says so, and policies show app IDs. It is tenant-wide: it lets the app read every app registration in the tenant, so you may prefer to skip it and track the secret’s expiry date yourself.
- Select Grant admin consent for your directory. Until consent is granted, every call is refused with
Authorization_RequestDenied.
One app registration can serve Azure, Entra ID, Intune and Microsoft Sentinel if it has all their permissions; each is still connected separately in Proofroom. Proofroom never writes to Entra ID.
Connect
| Field | Value |
|---|---|
| Directory (tenant) ID | From step 1 (or a verified domain) |
| Application (client) ID | From step 1 |
| Client secret | From step 2 |
Test connection signs in and calls the users list, role assignments, groups, the audit log, security defaults, Secure Score and the MFA registration report, naming the permission to grant for any that is refused. GroupMember.Read.All, Policy.Read.All (added in 1.12) and SecurityEvents.Read.All (added in 1.14.2) are warnings: the test passes and says which collector will fail until the permission is granted (Admin and privileged roles while a group holds an admin role; MFA enforcement; Microsoft Secure Score). Those collectors still fail their run, naming the permission. A refusal of any other permission fails the test.
When the client secret expires
After Test connection, and at most once a day after a run, Proofroom reads the app registration
(GET /applications(appId='{client ID}')?$select=displayName,passwordCredentials) and finds the secret in use by its
hint: Microsoft keeps the first three characters of each secret. The hint is used only for that match. The
integration page names the secret by its description and the last four characters of its key ID (an identifier, not
part of the secret), for example Client secret "Proofroom" (…a1b2), with its expiry date, and admins are emailed 30
and 7 days before it. Proofroom never shows any part of the secret. This needs Application.Read.All: an app cannot
read its own registration with client credentials without it, and it is the least privileged permission that can.
It is optional and tenant-wide (it lets the app read every app registration in the tenant), so you may prefer to skip
it and track the expiry date yourself; without it, the page says the expiry could not be read. If several secrets
start with the same three characters, the earliest expiry is shown.
Microsoft Secure Score
Secure Score is Microsoft’s measure of how far the tenant follows its security recommendations for the services it has (Entra ID, Exchange, SharePoint, Intune, Defender). It is a configuration-posture measure, filed against PCI DSS 2.2.1 (configuration standards applied) and SOC 2 CC7.1 (configuration monitoring); it does not prove any one control operates, so the evidence says so. Only the improvement actions the score lists for the tenant are shown; retired (deprecated) actions are left out. On Posture, the newest Secure Score evidence (up to 120 days old) counts with a weight of 10, split over Microsoft’s categories by their points: Identity in Identity and MFA, Data in Data protection, Device in Endpoints, Apps and Infrastructure in Network and cloud security. Each earns its share of the points it scores, and “pulling it down” names the action with the most points left. A new tenant gets its first score within about a day; until then the run fails saying so.
How MFA enforcement is judged
- A policy requires MFA when its grant asks for multifactor authentication, or for an authentication strength whose every allowed combination is multifactor. If it accepts another control instead (operator OR with, say, a compliant device), MFA is optional and the policy does not count; this is listed as a gap.
- Authentication strengths are named in the rule. Proofroom reads each strength’s allowed combinations (Graph returns them with the policy; if not, it reads the strength by ID). A combination of two or more methods counts as multifactor, as do Windows Hello for Business, FIDO2 security keys, multifactor certificates, passwordless phone sign-in, a Temporary Access Pass and federated MFA on their own. Any other method alone (a password, SMS, voice, email, a one-time code, an Authenticator push, federated single factor, a single-factor certificate) is a single factor: a strength that allows one does not count as MFA, and the gap names the single-factor combinations. A strength that cannot be read is named, is not counted as MFA, and a note says why.
- State: enforced (on), report-only (evaluated, not enforced) or off.
- MFA is required for everyone when an enforced policy requires MFA for all users and all apps, excludes no user, group, role or guest, and has no condition that narrows it (platforms, locations, client app types, sign-in, user or insider risk, device filters, authentication flows, user actions, workload identities). Security defaults never count as everyone: they are listed with users “admins at every sign-in; other users when Entra judges it necessary”, and the gap says that users who are not administrators are asked for MFA only when Entra ID judges it necessary.
- Required for administrators is yes when security defaults are on or a policy requires MFA for everyone, and no when nothing enforced requires MFA. Otherwise it is left unknown: Proofroom does not judge whether role-scoped policies reach every administrator role.
- When it is not, each gap is named: every excluded user, group, role or guest type; report-only and switched-off MFA policies; conditions that narrow an MFA policy; MFA offered as one choice among others. If security defaults are off and there is no Conditional Access, that is said plainly.
- Microsoft recommends excluding one or two emergency access (break-glass) accounts from Conditional Access. Proofroom still lists them as gaps, marked when the name says so, so each exclusion is reviewed and justified.
- Users, groups and roles in policies are shown by name. App IDs are shown by name with Application.Read.All, or as the ID without it. “All”, “Office 365” and “Microsoft admin portals” are shown in words.
Inactive accounts
- Last sign-in is Microsoft’s lastSuccessfulSignInDateTime: the last successful sign-in, interactive or not. The other two dates (lastSignInDateTime, lastNonInteractiveSignInDateTime) include failed attempts, so an unused account under a password spray would look active. Microsoft records successful sign-ins only since December 2023, so “never” can also mean none since then; either way the account is past the 90-day threshold.
- An account never signed in counts as inactive once it is older than 90 days.
- Disabled accounts are left out: they cannot sign in until enabled again. Guests are listed with status “guest”.
- Administrator status is not shown here; the Admin and privileged roles evidence has it.
Known limits
- Audit log retention: Entra ID keeps audit events 7 days on the free tier and 30 days with P1 or P2. With P1 or P2, the monthly default covers the whole window. On the free tier a monthly run covers only the last 7 days of the month, and the evidence says so; Proofroom does not read the licence, so the note appears whenever the window is longer than 7 days.
- Without P1 or P2, the MFA collector reads one user every 2 seconds to stay within Microsoft’s limit for identity reports, and may take up to an hour; a tenant too large for that fails the run with a message.
- Without P2, Privileged Identity Management cannot be read: permanent and active assignments are filed, and the
evidence says eligible ones are missing. Proofroom says this only when Microsoft Graph answers that the licence is
missing (
AadPremiumLicenseRequired). If Graph refuses because the app lacks a permission, or refuses for a reason Proofroom does not recognise, the run fails and names Graph’s answer, so eligible admins are never left out quietly. - A disable recorded only as an “Update user” event is not listed as a leaver.
- Without P1 or P2, sign-in activity is not recorded, so the inactive accounts collector fails with a message saying it needs Entra ID P1 or P2, and Conditional Access cannot be used; the MFA enforcement evidence then rests on security defaults.
- Leaver lag matches the People directory’s email with the user principal name in the audit log. Where they differ, the person shows as not removed in the window.
- Admin rights granted just in time through PIM for Groups (group membership, not role assignment) are not read.
Unverified
These were built from Microsoft’s documentation and not yet seen on a live tenant:
- The error Microsoft Graph sends for Conditional Access on a tenant without P1. Proofroom treats
Authentication_RequestFromNonPremiumTenantOrB2CTenantorAadPremiumLicenseRequiredas “not licensed”; any other refusal fails the run. A tenant without P1 may instead answer with an empty list, which reads the same way. - The licence error for sign-in activity: community reports show HTTP 403
Authentication_RequestFromNonPremiumTenantOrB2CTenant; Microsoft’s page states the licence need but not the code. - Microsoft documents the
ConsistencyLevel: eventualheader and$count=trueas required for the group members cast; Proofroom sends both. - That Graph always returns a policy’s authentication strength with its allowed combinations (Microsoft’s example shows it). When it does not, Proofroom reads the strength by ID with Policy.Read.All (Microsoft lists it as a higher-privileged permission for that call).