Back to Checks
azure

Non-privileged user has multi-factor authentication enabled

entra_non_privileged_user_has_mfa
Service: entraSeverity: medium
OfficialBuilt-inVerified
Categories:identity-accesse3
Resource Type:NotDefined

Microsoft Entra non-privileged users are assessed for multifactor authentication by verifying they have two or more registered authentication methods (MFA enrollment).

Risk

Absent MFA on standard accounts enables password-only logins after phishing, reuse, or spraying, leading to account takeover. Attackers can access email, files, and apps, send internal phishing, and escalate, undermining confidentiality and integrity, and risking availability via malicious changes.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks entra_non_privileged_user_has_mfa

Recommendation

Enforce MFA for all users, including non-privileged. Prefer phishing-resistant methods (FIDO2/passkeys or Authenticator with number matching); avoid SMS/voice when possible. Use Conditional Access to require MFA by risk and context. Pair with least privilege, device trust, and sign-in monitoring.

Remediation

CLI

az rest --method POST --url https://graph.microsoft.com/v1.0/users/<example_user_id>/authentication/temporaryAccessPassMethods --body '{"lifetimeInMinutes":60,"isUsableOnce":true}'

Other

1Sign in to the Microsoft Entra admin center
2Go to Entra ID > Users and select the non-privileged user
3Select Security > Authentication methods
4Click Add authentication method > Temporary Access Pass
5Click Create (accept defaults)
6Confirm the method appears under the user's authentication methods

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.entra.entra_client import entra_client
from prowler.providers.azure.services.entra.lib.user_privileges import (
    is_privileged_user,
)


class entra_non_privileged_user_has_mfa(Check):
    def execute(self) -> Check_Report_Azure:
        findings = []

        for tenant_domain, users in entra_client.users.items():
            if tenant_domain in entra_client.users_retrieval_errors:
                report = Check_Report_Azure(metadata=self.metadata(), resource={})
                report.subscription = f"Tenant: {tenant_domain}"
                report.resource_name = tenant_domain
                report.resource_id = entra_client.tenant_ids[0]
                report.status = "MANUAL"
                report.status_extended = (
                    f"Cannot evaluate MFA for the tenant's non-privileged users for tenant {tenant_domain}: "
                    f"Microsoft Graph did not return the tenant's users "
                    f"({entra_client.users_retrieval_errors[tenant_domain]}). "
                    f"Retry the scan or review the tenant's users manually."
                )
                findings.append(report)
                continue

            for user in users.values():
                if user.account_enabled and not is_privileged_user(
                    user, entra_client.directory_roles[tenant_domain]
                ):
                    report = Check_Report_Azure(metadata=self.metadata(), resource=user)
                    report.subscription = f"Tenant: {tenant_domain}"
                    report.status = "FAIL"
                    report.status_extended = (
                        f"Non-privileged user {user.name} does not have MFA."
                    )

                    if user.is_mfa_capable:
                        report.status = "PASS"
                        report.status_extended = (
                            f"Non-privileged user {user.name} has MFA."
                        )

                    findings.append(report)

        return findings