Conditional Access policy enforces approved client apps or app protection for mobile devices
Microsoft Entra Conditional Access policies can require that only approved client apps or apps with app protection policies are used on iOS and Android devices. This ensures corporate data on mobile platforms is accessed only through managed or protected applications.
Risk
Without requiring approved or protected client apps on mobile platforms, users can access corporate data through unmanaged applications that lack security controls. This increases the risk of data leakage, unauthorized data sharing, and exposure of sensitive information on personal or compromised mobile devices.
Run this check with Prowler
Run in Prowler Cloudprowler m365 --checks entra_conditional_access_policy_approved_client_app_required_for_mobileRecommendation
Enforce Conditional Access policies requiring app protection policies or approved client apps on iOS and Android devices. Prefer app protection policies over approved client apps, as the approved client app grant control is retiring June 30, 2026. Regularly review policies to ensure mobile access is restricted to managed applications.
Remediation
Other
Check Code
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.entra.entra_client import entra_client
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessGrantControl,
ConditionalAccessPolicyState,
GrantControlOperator,
)
class entra_conditional_access_policy_approved_client_app_required_for_mobile(Check):
"""Check if a Conditional Access policy requires approved client apps or app protection for mobile devices.
This check ensures that at least one enabled Conditional Access policy
targets iOS and Android platforms and requires approved client apps or
app protection policies.
- PASS: An enabled policy requires approved client apps or app protection for iOS/Android.
- FAIL: No policy restricts mobile app access to approved or protected apps.
"""
REQUIRED_MOBILE_PLATFORMS = {"android", "ios"}
MOBILE_APP_GRANT_CONTROLS = {
ConditionalAccessGrantControl.APPROVED_APPLICATION,
ConditionalAccessGrantControl.COMPLIANT_APPLICATION,
}
def execute(self) -> list[CheckReportM365]:
"""Execute the check logic.
Returns:
A list of reports containing the result of the check.
"""
findings = []
report = CheckReportM365(
metadata=self.metadata(),
resource={},
resource_name="Conditional Access Policies",
resource_id="conditionalAccessPolicies",
)
report.status = "FAIL"
report.status_extended = "No Conditional Access Policy requires approved client apps or app protection for mobile devices."
for policy in entra_client.conditional_access_policies.values():
if policy.state == ConditionalAccessPolicyState.DISABLED:
continue
if not policy.conditions.platform_conditions:
continue
included_platforms = set(
policy.conditions.platform_conditions.include_platforms
)
excluded_platforms = set(
policy.conditions.platform_conditions.exclude_platforms
)
targets_mobile_platforms = (
"all" in included_platforms
or self.REQUIRED_MOBILE_PLATFORMS.issubset(included_platforms)
) and not (
"all" in excluded_platforms
or self.REQUIRED_MOBILE_PLATFORMS.intersection(excluded_platforms)
)
if not targets_mobile_platforms:
continue
built_in_controls = set(policy.grant_controls.built_in_controls)
has_mobile_app_control = bool(
self.MOBILE_APP_GRANT_CONTROLS.intersection(built_in_controls)
)
if not has_mobile_app_control:
continue
if (
policy.grant_controls.operator == GrantControlOperator.OR
and not built_in_controls.issubset(self.MOBILE_APP_GRANT_CONTROLS)
):
continue
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.display_name,
resource_id=policy.id,
)
if policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
report.status = "FAIL"
report.status_extended = f"Conditional Access Policy {policy.display_name} reports the requirement of approved client apps or app protection for mobile devices but does not enforce it."
else:
report.status = "PASS"
report.status_extended = f"Conditional Access Policy {policy.display_name} requires approved client apps or app protection for mobile devices."
break
findings.append(report)
return findings