Les licences Microsoft 365 inutilisées grèvent silencieusement votre budget, tandis que les comptes Azure AD inactifs représentent un véritable risque de sécurité. Évitez les éléments superflus dans votre domaine en automatisant les vérifications avec l’API Graph de Microsoft pour identifier les licences expirées et les utilisateurs dormants.
Dans ce guide, nous vous aidons à planifier des vérifications essentielles via PowerShell afin de neutraliser les vulnérabilités et de déployer la méthode à l’échelle de tous vos clients.
Pour un aperçu visuel rapide, regardez notre guide vidéo Comment planifier des vérifications via l’API Graph pour les licences expirées et les utilisateurs inactifs.
Procédure détaillée pour planifier des vérifications de l’API Graph via PowerShell
Automatisez les vérifications de l’API Graph pour récupérer les licences gaspillées, sécuriser les comptes dormants, respecter la conformité et simplifier la gestion des locataires, le tout en une seule passe.
📌 Cas d’utilisation : appliquez cette méthode lors des revues mensuelles de coûts, des audits de sécurité ou avant les renouvellements de licences. Elle est idéale pour les fournisseurs de services gérés qui souhaitent récupérer des licences Office 365 expirées ou renforcer la sécurité après le départ d’un collaborateur. Elle permet aussi de repérer les utilisateurs inactifs avant qu’ils ne deviennent des vulnérabilités pour votre système.
📌 Prérequis : avant de commencer, assurez-vous de disposer des éléments suivants :
- Autorisations d’administration : votre compte doit disposer du rôle Global Admin ou Reports Reader dans Azure AD.
- Outils : Microsoft Graph PowerShell SDK (module Microsoft.Graph) et PowerShell 7+.
- Configuration Azure : votre application Azure AD doit disposer des autorisations User.Read.All, LicenseAssignment.ReadWrite.All et AuditLog.Read.All pour l’automatisation.
- Facultatif mais recommandé : téléchargez et installez un outil RMM comme NinjaOne pour planifier les scripts, surveiller les résultats et déployer la méthode sur plusieurs locataires.
Nous vous conseillons de consulter la section ⚠️ Points de vigilance avant de poursuivre.
Étape 1 : installer et authentifier le SDK Microsoft Graph
Préparez votre boîte à outils pour automatiser les vérifications de licences et d’utilisateurs. L’installation du SDK Graph permet d’interroger les données Azure AD (généralement masquées par l’administrateur) et l’authentification relie votre script à l’API de Microsoft.
Procédure détaillée :
- Installez le SDK en exécutant ce script dans PowerShell (Admin) ou Windows Terminal (Admin) :
Install-Module Microsoft.Graph -Scope CurrentUser -Force
- Authentifiez-vous à l’aide de ce script :
Connect-MgGraph -Scopes "User.Read.All", "Reports.Read.All", "Directory.Read.All"
Vous pouvez également configurer une application enregistrée avec un client secret et utiliser un flux par certificat ou par identifiants client pour une exécution sans surveillance.
Une fois le SDK Graph authentifié, vous pourrez interroger les utilisateurs Azure AD inactifs et les licences Office 365 expirées dans les étapes suivantes.
Étape 2 : rechercher les utilisateurs dont les licences sont expirées ou non attribuées
Cette étape permet de mettre au jour les licences expirées et les comptes inactifs, sources de risques de sécurité et de coûts inutiles.
Procédure détaillée :
- Dans PowerShell (Admin), exécutez ce script pour rechercher les licences non attribuées au niveau du locataire :
Get-MgSubscribedSku |Select-Object SkuPartNumber,@{Name="TotalLicenses"; Expression={$_.PrepaidUnits.Enabled}},@{Name="UsedLicenses"; Expression={$_.ConsumedUnits}},@{Name="Available"; Expression={$_.PrepaidUnits.Enabled - $_.ConsumedUnits}} |Format-Table -AutoSize
- Exécutez ce script pour identifier les utilisateurs sans licence :
Get-MgUser -Filter "assignedLicenses/`$count eq 0" `-ConsistencyLevel eventual `-CountVariable unlicensedCount `-All |Select-Object DisplayName, UserPrincipalName |Export-Csv -Path "UnlicensedUsers.csv" -NoTypeInformation
- Exécutez ce script pour identifier les utilisateurs inactifs possédant une licence :
$daysInactive = 90$cutoffDate = (Get-Date).AddDays(-$daysInactive)# Get licensed inactive usersGet-MgUser -All -Property "DisplayName,UserPrincipalName,SignInActivity,AssignedLicenses" |Where-Object {($_.SignInActivity.LastSignInDateTime -lt $cutoffDate) -and($_.AssignedLicenses.Count -gt 0)} |Select-Object DisplayName,UserPrincipalName,@{Name="LastSignIn"; Expression={$_.SignInActivity.LastSignInDateTime}} |Export-Csv -Path "InactiveLicensedUsers.csv" -NoTypeInformation
⚠️ Important : n’oubliez pas que SignInActivity nécessite Azure AD Premium P1/P2. Évitez également les points de terminaison bêta pour les scripts de production.
À l’issue de ces scripts, vous obtiendrez deux fichiers CSV : UnlicensedUsers.csv, qui recense les utilisateurs nécessitant l’attribution d’une licence, et InactiveLicensedUsers.csv, qui liste les comptes constituant un risque de sécurité.
Étape 3 : exporter et consigner les résultats d’audit
Après avoir obtenu la liste des licences expirées et non attribuées, transformez ces données en informations exploitables grâce au reporting automatisé. L’export de ces données crée des pistes d’audit permanentes qui prouvent votre conformité, et l’automatisation vous permet de détecter les anomalies avant qu’elles ne coûtent cher.
Procédure détaillée :
- Dans PowerShell (Admin), exécutez ce script pour exporter vers un fichier CSV horodaté :
- Script pour générer un nom de fichier horodaté :
$timestamp = Get-Date -Format "yyyyMMdd-HHmm"$reportPath = "C:\Audits\LicenseReport_$timestamp.csv"
- Exportez les utilisateurs inactifs possédant une licence :
$inactiveUsers | Export-Csv -Path $reportPath -NoTypeInformation
- Vous obtiendrez des fichiers CSV lisibles par n’importe quel outil, et l’horodatage crée des enregistrements versionnés à des fins de conformité.
- (Facultatif) : exécutez ce script pour envoyer les rapports par e-mail :
Send-MailMessage -From "[email protected]" -To "[email protected]" `-Subject "ACTION REQUIRED: $($inactiveUsers.Count) Inactive Licensed Users" `-Body "Attached: Users with licenses but no sign-ins for 90+ days" `-Attachments $reportPath -SmtpServer "smtp.office365.com" -Port 587 `-Credential (Get-Credential)
- Exécutez ce script pour automatiser entièrement le processus avec l’application Azure AD :
$tenantId = "YOUR_TENANT_ID"$clientId = "YOUR_CLIENT_ID"$clientSecret = "YOUR_SECRET" | ConvertTo-SecureString -AsPlainText -ForceConnect-MgGraph -TenantId $tenantId -ClientId $clientId -ClientSecret $clientSecret
💡 Conseil : stockez les secrets dans Azure Key Vault. Ne les codez jamais en dur.
À l’issue de ces scripts, vous disposerez de rapports CSV horodatés stockés localement et, en option, d’alertes e-mail envoyées instantanément aux parties prenantes. Ces fichiers peuvent ensuite être générés automatiquement via le planificateur de tâches ou des outils RMM comme NinjaOne, pour une surveillance continue.
Étape 4 : automatiser avec le planificateur de tâches ou une politique RMM
Planifiez votre script une seule fois et laissez-le s’exécuter chaque mois, chaque année ou indéfiniment, pour une surveillance proactive sans lever le petit doigt. Des contrôles réguliers permettent de détecter les anomalies avant qu’elles ne posent problème. Deux options s’offrent à vous :
Option 1 : via le planificateur de tâches (machine unique)
Procédure détaillée :
- Ouvrez l’invite de commande (Admin), puis exécutez cette commande :
schtasks /create /tn "M365LicenseAudit" /tr `"powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\LicenseAudit.ps1" `/sc weekly /d MON /st 02:00 /ru "NT AUTHORITY\SYSTEM"
- Cette méthode fonctionne car le script s’exécute sous un compte système, même lorsqu’aucun utilisateur n’est connecté.
Option 2 : via un outil RMM
Procédure détaillée :
- Ouvrez l’outil RMM de votre choix, par exemple NinjaOne.
- Créez le script (celui de l’option 1), puis enregistrez-le dans la bibliothèque de scripts de NinjaOne.
- Attribuez le script au groupe de politiques Microsoft 365 Clients.
- Configurez les sorties :
- Enregistrez les fichiers CSV dans \\ClientShare\Audits.
- Chargez-les sur le tableau de bord de l’outil RMM pour une consultation centralisée.
Une fois le script planifié, il s’exécutera à la date et à l’heure définies, enregistrera automatiquement les rapports dans les dossiers désignés et fera apparaître les tendances entre les locataires.
⚠️ Points de vigilance
Cette section met en lumière les difficultés éventuelles à garder en tête lorsque vous suivez ce guide.
| Risques | Conséquences possibles | Solutions |
| 1. Données manquantes dans les rapports | Audits incomplets, risques non détectés | Vérifiez les autorisations : exécutez Get-MgContext pour contrôler les portées telles que User.Read.All.Contournez les blocages liés à la MFA (authentification forte) : utilisez l’authentification par certificat plutôt que par secret. |
| 2. Le script échoue sans avertissement | Faux sentiment de sécurité, manquements à la conformité | Activez la journalisation : ajoutez Start-Transcript -Path C:\Logs\Audit.log aux scripts.Surveillez l’observateur d’événements : consultez Journaux (Applications and Services Logs) > PowerShell. |
| 3. Utilisateurs non signalés | Licences expirées ou comptes inactifs passés entre les mailles du filet | Validez les seuils : vérifiez que $cutoffDate correspond bien à votre politique. Contrôlez les champs de licence : utilisez |
| 4. Secrets codés en dur | Compromission du locataire, vol d’identifiants | Renouvelez immédiatement les secrets dans Azure AD. Migrez vers Azure Key Vault : utilisez |
| 5. Dépendance à l’API bêta | Le script cesse de fonctionner après une mise à jour de Microsoft | Remplacez les points de terminaison bêta : utilisez Get-MgUser (v1.0) au lieu de Get-MgBetaUser.Abonnez-vous au journal des modifications de Microsoft Graph. |
Éléments clés pour des audits PowerShell de l’API Graph à toute épreuve
Ajustez ces paramètres à votre environnement. La précision évite les fausses alertes et garantit la fluidité des flux de travail.
Exclusions dans les rapports
Excluez les comptes de service, les boîtes aux lettres partagées et les comptes d’urgence (break-glass) des analyses d’inactivité. Vous éviterez ainsi de récupérer par erreur des licences liées à des ressources critiques. Vous pouvez recourir à des filtres PowerShell pour les placer sur liste blanche, avec ce script :
$excludedUPNs = @("[email protected]", "[email protected]")Get-MgUser | Where-Object { $_.UserPrincipalName -notin $excludedUPNs }
Seuils d’inactivité
Définissez les seuils en fonction de votre tolérance au risque. Un compte inactif depuis 90 jours présente un risque faible, 60 jours un risque moyen et 30 jours un risque élevé. Selon le niveau de risque, envoyez des e-mails d’avertissement, révoquez les licences ou désactivez le compte avant de récupérer la licence. Vous vous prémunissez ainsi contre les problèmes.
Fréquence des audits
Planifiez vos audits au bon moment pour éviter les risques de sécurité et autres désagréments. Pour la plupart des entreprises, des vérifications mensuelles calées sur les cycles de facturation sont recommandées.
Dans les secteurs à forte rotation de l’emploi, des vérifications hebdomadaires permettent aux rapports de suivre l’évolution de l’environnement. Déclenchez également un audit dès qu’un collaborateur quitte l’entreprise.
Correspondance entre constats et actions
Élaborez des procédures qui déclenchent automatiquement les étapes suivantes. Exécutez les scripts ci-dessous pour récupérer les licences et désactiver les comptes :
- Pour récupérer les licences :
Set-MgUserLicense -UserId "[email protected]" -RemoveLicenses @("skuId")
- Pour désactiver les comptes :
Update-MgUser -UserId "[email protected]" -AccountEnabled:$false
Une fois ces scripts exécutés, archivez les données. Transmettez-les au responsable ou à SharePoint via l’API Graph.
Comment NinjaOne simplifie vos audits de licences
Transformez les vérifications de l’API Graph en véritables moteurs de conformité multi-locataires entièrement automatisés, là où il fallait auparavant tout faire à la main.
- Déploiement centralisé des scripts : envoyez vos scripts PowerShell dédiés à l’API Graph vers plus de 100 terminaux ou locataires en une seule action.
- Surveillance automatique des résultats : suivez les rapports et journaux CSV de tous vos clients. Les alertes se déclenchent instantanément si les fichiers ne sont pas mis à jour.
- Alertes d’échec dans vos outils : recevez des notifications Slack, Teams ou e-mail en cas d’échec d’un script.
- Rapports unifiés multi-locataires : regroupez les données sur les licences Office 365 expirées et les utilisateurs inactifs dans un seul tableau de bord de direction.
- Remédiation déclenchée automatiquement : créez automatiquement des tickets dans votre outil PSA, avec des procédures prédéfinies pour détecter les licences expirées.
Maîtrisez vos coûts et votre sécurité grâce aux vérifications de licences via l’API Graph
Automatiser les audits de licences et d’utilisateurs fait passer d’une supervision réactive à un véritable contrôle proactif. En récupérant les licences inutilisées et en désactivant les comptes dormants, vous évitez les fuites de facturation et fermez des vecteurs d’attaque. Appliquez la procédure ci-dessus pour convertir les licences inutilisées en économies budgétaires et les comptes obsolètes en conformité.
Guide de démarrage rapide
NinjaOne vous aide à planifier des vérifications via l’API Graph pour les licences expirées et les utilisateurs inactifs. La plateforme NinjaOne propose des outils et des conseils pour :
- Auditer les licences expirées : utilisez l’API Graph pour identifier les licences dont la date d’expiration est dépassée
- Repérer les utilisateurs inactifs : détectez les utilisateurs qui ne se sont pas connectés ou n’ont pas utilisé les services sur une période donnée
- Automatiser ces vérifications : configurez des tâches planifiées pour réaliser ces audits régulièrement
Sujets connexes
- 8 bonnes pratiques pour sécuriser les API
- Comment alerter sur les comptes utilisateurs inactifs sous Linux : guide complet avec scripts
- Automatiser la détection des comptes utilisateurs inactifs avec PowerShell
- Identifier et gérer les comptes locaux inutilisés sur les systèmes Windows
- Guide complet pour désactiver des comptes utilisateurs sous Linux, à l’intention des professionnels de l’informatique
