# Application Access Policy est obsolète : ce que ça change pour votre posture de sécurité Azure 

## 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`](http://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`](http://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)](https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access)

## 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](https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac)

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 :

1.  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.
    
2.  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

```shell
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](http://Mail.Read) scopé à un Admin Unit) :

powershell

```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.

## Comment migrer une app existante

Microsoft documente un chemin de migration officiel, sans interruption de service pour l'app :

1.  **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.
    
2.  **Créer le Service Principal pointer** dans Exchange Online (`New-ServicePrincipal`), qui référence le service principal Entra ID existant.
    
3.  **Assigner le rôle applicatif RBAC** correspondant à la permission (ex: `Application Mail.ReadWrite`) avec le Management Scope créé en étape 1.
    
4.  **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).
    
5.  **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

```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`](mailto:boite1@company.fr) et [`boite2@company.fr`](mailto: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) :

*   **AppId** (Application ID)
    
*   **ObjectId** du service principal (Object ID de l'Enterprise Application, différent de l'ObjectId de l'App Registration)
    

Vous pouvez aussi les récupérer en PowerShell :

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

```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

```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

```powershell
New-ServicePrincipal -AppId "<AppId-de-App1>" -ObjectId "<ObjectId-du-ServicePrincipal>" -DisplayName "App1"
```

Résultat attendu :

```plaintext
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

```powershell
Get-Group -Identity "App1-Mail-Scope@company.fr" | Select-Object DistinguishedName
```

Créer le scope avec ce DN :

powershell

```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`](http://Mail.Read) est `Application` [`Mail.Read`](http://Mail.Read) :

powershell

```powershell
New-ManagementRoleAssignment -App "<ObjectId-du-ServicePrincipal>" -Role "Application Mail.Read" -CustomResourceScope "App1-Scope"
```

Résultat attendu :

```plaintext
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](http://Mail.Read)

Si App1 possédait déjà la permission [`Mail.Read`](http://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`](http://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

```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`](mailto: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`](http://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 :**

*   [Role Based Access Control for Applications in Exchange Online](https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac)
    
*   [Application Access Policies (legacy)](https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access)
