Vous connaissez sans doute déjà Application Access Policy
Si vous gérez des App Registrations qui accèdent aux mailboxes Exchange Online via Microsoft Graph (Mail.Read, Mail.ReadWrite, Mail.Send, Calendars.*, Contacts.*...), vous avez probablement déjà utilisé Application Access Policy. C'est le mécanisme historique configurable uniquement en PowerShell Exchange Online (New-ApplicationAccessPolicy) qui permet de restreindre une app à un groupe de sécurité mail-enabled plutôt que de la laisser accéder à toutes les boîtes du tenant.
C'était, et ça reste techniquement, une bonne solution. Elle a permis pendant des années de compenser un comportement par défaut risqué de Microsoft Entra ID : dès qu'une app obtient une permission Graph de type Mail.Read en mode Application, elle peut par défaut lire toutes les boîtes du tenant, sans discrimination.
Documentation officielle : Limit application permissions to specific mailboxes (legacy)
Mais Microsoft présente désormais mieux : RBAC for Applications
Microsoft a introduit RBAC for Applications in Exchange Online, et le message est sans ambiguïté :
"App Access Policies has been replaced by Role Based Access Control for Applications... New access configuration should not use Application Access Policies since this feature will have deprecation announced in the future which will require migration."
Documentation officielle : Role Based Access Control for Applications in Exchange Online
Ce n'est pas un simple renommage. Le modèle d'autorisation change fondamentalement.
La différence fondamentale : restreindre un accès large vs. accorder un accès précis
C'est le point le plus important à comprendre, et il change complètement la façon de raisonner sur la sécurité de vos apps.
Application Access Policy : on donne tout, puis on restreint
Avec ce modèle, le flux est en deux temps :
Vous consentez la permission Graph (Mail.ReadWrite par exemple) dans Microsoft Entra ID → par défaut, l'app a accès à toutes les boîtes du tenant.
Vous appliquez une Application Access Policy pour filtrer cet accès et le limiter à un groupe de boîtes.
La policy ne fait que restreindre un droit déjà accordé. Sans elle, l'app a un accès total. Avec elle, l'app est bridée , mais le potentiel d'accès total reste sous-jacent, porté par le consentement Entra ID.
Exemple :
powershell
New-ApplicationAccessPolicy -AppId <AppId> -PolicyScopeGroupId EvenUsers@contoso.com -AccessRight RestrictAccess -Description "Restrict this app to members of distribution group EvenUsers."
RBAC for Applications : on accorde un accès précis, dès le départ
Ici, la logique est inversée. Le droit et le scope sont accordés ensemble, en une seule opération, directement dans Exchange Online RBAC — sans dépendre d'un consentement Entra ID préalable.
"RBAC for Applications... allows admins to grant permissions to an application that's independently accessing data in Exchange Online. This grant can be paired with a scope of access."
Une app sans aucune permission Graph classique peut recevoir un rôle applicatif RBAC scopé sur une seule boîte, et ça fonctionne, l'app accède à cette boîte et uniquement celle-ci, sans jamais être passée par un consentement tenant-wide.
Exemple (accès Mail.Read scopé à un Admin Unit) :
powershell
New-ServicePrincipal -AppId eb19847b-5563-42ea-b719-ea47cb0cf4b3 -ObjectId 59b7c6cb-58d3-4ee8-a409-8c1f9dbb5d36 -DisplayName "example"
New-ManagementRoleAssignment -App 59b7c6cb-58d3-4ee8-a409-8c1f9dbb5d36 -Role "Application Mail.Read" -RecipientAdministrativeUnitScope 4d819ce9-9257-44d7-af20-68a49e6697f4
Attention : les deux systèmes ne se remplacent pas automatiquement l'un l'autre
Point critique que la documentation souligne explicitement : les permissions issues des deux systèmes s'additionnent, elles ne se plafonnent pas mutuellement.
"The permissions assigned using Application RBAC act in addition to grants you make in Microsoft Entra ID... the assigned permissions are a union operation on the permissions from Microsoft Entra ID and the permissions assigned in Exchange Online RBAC."
Concrètement : si une app a déjà Mail.ReadWrite non scopé dans Entra ID, ajouter un rôle RBAC scopé à une seule boîte ne réduit rien , l'app garde son accès total, car le RBAC scopé s'ajoute au droit déjà large, il ne le remplace pas. Il faut explicitement retirer le consentement Entra ID pour que le scoping RBAC devienne effectif.
Dans quel cas utiliser l'un ou l'autre ?
La documentation officielle tranche clairement :
"We don't expect Application Access Policies to be typically used with RBAC for Applications. Organization-wide permissions should be assigned in Microsoft Entra ID while resource-scoped permissions should be granted using RBAC for Applications."
En clair, plus de zone grise, un choix par app :
| Besoin |
Solution recommandée |
| L'app doit légitimement accéder à toutes les boîtes (ex: outil de sécurité, backup, eDiscovery) |
Consentement Graph classique dans Entra ID, sans policy ni RBAC scoping |
| L'app ne doit accéder qu'à un sous-ensemble de boîtes (la majorité des cas métier) |
RBAC for Applications uniquement, avec retrait du consentement Graph classique |
Application Access Policy ne devrait plus apparaître dans aucun de ces deux cas.
Pourquoi migrer maintenant
Application Access Policy est officiellement qualifiée de legacy. Une dépréciation formelle sera annoncée par Microsoft dans le futur, avec obligation de migration. Anticiper cette migration permet d'éviter un chantier subi dans l'urgence, et surtout d'adopter dès maintenant un modèle de sécurité plus rigoureux : un scope d'accès précis et natif, plutôt qu'un accès large filtré a posteriori.
Microsoft documente un chemin de migration officiel, sans interruption de service pour l'app :
Créer un Management Scope qui pointe vers le groupe de sécurité déjà utilisé par l'Application Access Policy, via un filtre MemberOfGroup sur le distinguished name du groupe.
Créer le Service Principal pointer dans Exchange Online (New-ServicePrincipal), qui référence le service principal Entra ID existant.
Assigner le rôle applicatif RBAC correspondant à la permission (ex: Application Mail.ReadWrite) avec le Management Scope créé en étape 1.
Retirer le consentement de la permission dans Entra ID — étape indispensable, sans quoi le scoping RBAC n'a aucun effet réel (cf. section ci-dessus).
Supprimer l'Application Access Policy devenue obsolète.
Point de vigilance : les groupes imbriqués ne sont pas supportés par le filtre MemberOfGroup — seule l'appartenance directe au groupe est prise en compte. À vérifier avant toute migration si vos groupes de scoping actuels contiennent des groupes imbriqués.
Validation post-migration :
powershell
Test-ServicePrincipalAuthorization -Identity <AppId> -Resource <mailbox-cible>
Exemple pas à pas : donner à App1 un accès en lecture sur deux boîtes précises
Cas concret : vous avez une App Registration App1 dans Entra ID, et vous voulez qu'elle puisse lire uniquement les boîtes boite1@company.fr et boite2@company.fr , rien d'autre.
L'approche la plus simple et la plus proche de ce que vous connaissiez avec Application Access Policy consiste à réutiliser un groupe de sécurité mail-enabled comme périmètre, via un Management Scope filtré sur ce groupe. Voici tous les steps.
Étape 1 — Récupérer les identifiants de App1 dans Entra ID
Dans Microsoft Entra admin center > Enterprise Applications (pas App Registrations, les IDs diffèrent) :
Vous pouvez aussi les récupérer en PowerShell :
powershell
Connect-MgGraph -Scopes "Application.Read.All"
Get-MgServicePrincipal -Filter "AppId eq '<AppId-de-App1>'" | Select-Object DisplayName, AppId, Id
Id ici correspond à l'ObjectId du service principal à utiliser à l'étape 3.
Étape 2 — Créer le groupe de sécurité mail-enabled et y ajouter les deux boîtes
powershell
Connect-ExchangeOnline -UserPrincipalName admin@company.fr
New-DistributionGroup -Name "App1-Mail-Scope" -Alias "App1-Mail-Scope" -Type Security -PrimarySmtpAddress "App1-Mail-Scope@company.fr"
Add-DistributionGroupMember -Identity "App1-Mail-Scope@company.fr" -Member "boite1@company.fr"
Add-DistributionGroupMember -Identity "App1-Mail-Scope@company.fr" -Member "boite2@company.fr"
Vérification :
powershell
Get-DistributionGroupMember -Identity "App1-Mail-Scope@company.fr"
⚠️ Rappel du doc : pas de groupes imbriqués. Les deux boîtes doivent être membres directs du groupe.
Étape 3 — Créer le pointeur Service Principal dans Exchange Online
powershell
New-ServicePrincipal -AppId "<AppId-de-App1>" -ObjectId "<ObjectId-du-ServicePrincipal>" -DisplayName "App1"
Résultat attendu :
DisplayName ObjectId AppId
----------- -------- -----
App1 <ObjectId> <AppId>
Étape 4 — Créer le Management Scope pointant vers le groupe
Pour scoper sur les membres du groupe créé en étape 2, on utilise un filtre MemberOfGroup sur le distinguished name (DN) du groupe — pas son adresse mail.
Récupérer le DN du groupe :
powershell
Get-Group -Identity "App1-Mail-Scope@company.fr" | Select-Object DistinguishedName
Créer le scope avec ce DN :
powershell
New-ManagementScope -Name "App1-Scope" -RecipientRestrictionFilter "MemberOfGroup -eq 'CN=App1-Mail-Scope,OU=company.fr,OU=Microsoft Exchange Hosted Organizations,DC=NAMPR00A001,DC=prod,DC=outlook,DC=com'"
(Remplacez le DN par la valeur exacte retournée par Get-Group à l'étape précédente.)
Étape 5 — Assigner le rôle applicatif "lecture mail" à App1 avec ce scope
Le rôle applicatif correspondant à Mail.Read est Application Mail.Read :
powershell
New-ManagementRoleAssignment -App "<ObjectId-du-ServicePrincipal>" -Role "Application Mail.Read" -CustomResourceScope "App1-Scope"
Résultat attendu :
Name Role RoleAssigneeName RoleAssigneeType AssignmentMethod
---- ---- ---------------- ---------------- ----------------
Application Mail.Rea... Application Mail.Read <ObjectId> ServicePrincipal Direct
Étape 6 — Nettoyer le consentement Entra ID si App1 avait déjà Mail.Read
Si App1 possédait déjà la permission Mail.Read (application permission) consentie côté Entra ID, il faut la retirer , sinon, comme expliqué plus haut, l'union des deux systèmes annule le scoping et App1 garde un accès à toutes les boîtes du tenant.
Dans Entra admin center > App registrations > App1 > API permissions, retirer Mail.Read (Application), puis retirer le consentement admin associé.
Si App1 n'avait aucune permission Graph consentie au préalable, cette étape n'est pas nécessaire , le rôle RBAC assigné en étape 5 suffit seul à donner l'accès.
Étape 7 — Tester le scope avant mise en production
powershell
Test-ServicePrincipalAuthorization -Identity "App1" -Resource "boite1@company.fr" | Format-Table
Test-ServicePrincipalAuthorization -Identity "App1" -Resource "boite2@company.fr" | Format-Table
Test-ServicePrincipalAuthorization -Identity "App1" -Resource "autre-boite@company.fr" | Format-Table
Résultat attendu : InScope = True pour boite1 et boite2, InScope = False pour toute autre boîte. Si le test sur autre-boite@company.fr remonte True, c'est le signe qu'un consentement Entra ID non retiré (étape 6) casse le scoping.
Objectif cible : plus aucune Application Access Policy
L'état cible recommandé n'est pas une coexistence des deux systèmes, mais une élimination complète d'Application Access Policy au profit de RBAC for Applications pour tout accès mail scopé :
Retirer les Application Access Policies existantes une fois la migration RBAC effectuée et validée.
Retirer les consentements Graph mail (Mail.Read, Mail.ReadWrite, Mail.Send, etc.) au niveau Entra ID pour toute app qui n'a pas de besoin légitime d'accès tenant-wide.
Ne conserver un accès Graph mail tenant-wide dans Entra ID que pour les apps dont le besoin métier le justifie explicitement, documenté et validé.
Cette approche réduit la surface d'attaque de façon native , le scope minimal est intégré au droit lui-même, il ne dépend plus d'une couche de filtrage supplémentaire susceptible d'être oubliée, mal configurée, ou contournée par un consentement Entra ID resté trop large.
Sources officielles :