Microsoft Graph OAuthAuthentifier les boîtes aux lettres Outlook et Microsoft 365
Un guide complet 2026 pour Microsoft Graph OAuth pour les développeurs SaaS. Couvre l'enregistrement des applications Microsoft Entra, les points de terminaison d'autorité, les étendues Mail, les autorisations déléguées vs d'application, le consentement de l'administrateur, le code d'autorisation + PKCE, la rotation des jetons de rafraîchissement, les codes d'erreur AADSTS, et comment Unipile élimine 5 semaines de travail de plomberie OAuth en 5 minutes.
import demandes
# Étape 1 : Générer un lien d'authentification hébergé
response = requests.poste(
"https://apiXXX.unipile.com:XXX
/api/v1/hébergé/comptes/lier",
en-têtes={"X-API-KEY": clé_api},
json={
"type": "créer",
"fournisseurs": ["MICROSOFT"],
"api_url": votre_dsn,
"expireLe": "2026-12-31T23:59:59Z"
}
)
# Étape 2 : Rediriger l'utilisateur vers l'URL
auth_url = réponse.json()["url"]
# Unipile gère l'intégralité du processus OAuth
#, comprenant Entra, les oscilloscopes, les jetons et la mise à jourPourquoi Microsoft Graph OAuth est non négociable en 2026
Si votre application SaaS lit, envoie ou synchronise des e-mails Outlook ou Microsoft 365, l'authentification OAuth de Microsoft Graph n'est plus facultative. Trois dépréciations majeures ont rendu obsolètes l'authentification de base, les protocoles hérités et les mots de passe d'application. L'authentification OAuth 2.0 via l'API Microsoft Graph est la seule voie prise en charge.
Les 3 flux OAuth pris en charge par Microsoft (et lequel est nécessaire pour les SaaS)
La plateforme d'identité de Microsoft prend en charge plusieurs types d'octroi OAuth 2.0. Choisir le mauvais type est une source courante de perte de temps d'ingénierie. Voici la répartition pour les applications SaaS qui accèdent à la messagerie au nom de leurs utilisateurs.
Enregistrement d'application Microsoft Entra : 7 étapes
Avant que votre application puisse demander des jetons OAuth, vous avez besoin d'une application enregistrée dans Microsoft Entra ID (anciennement Azure Active Directory). Voici les étapes exactes, y compris les valeurs de champs qui sont importantes et celles qui sont cosmétiques.
portal.azure.com, allez à Microsoft Entra ID (rechercher dans la barre supérieure), puis Enregistrements d'applications, puis cliquez + Nouvelle inscription. Voir le Documentation complète de Microsoft OAuth pour plus de contexte.Comptes dans tout répertoire organisationnel (n'importe quel tenant Microsoft Entra ID - multitenant) et comptes Microsoft personnels. Cela correspond à la /commun point de terminaison d'autorité./organisations l'autorité et réduit votre surface de consentement. Plus sur les points d'extrémité d'autorité dans la section 4.Web pour les applications côté serveur. Utiliser Application monopage (SPA) pour les flux côté client (active PKCE automatiquement).https://app.yourproduct.com/auth/microsoft/callback. Correspondance exacte requise, toute déviation entraîne AADSTS50011.http://localhost:3000/callback) mais les URI de production doivent utiliser HTTPS. Enregistrez les deux séparément.Mail.Read, accès_hors_ligne, openid, profilMail.ReadWrite, Mail.Send, accès_hors_ligne, openid, profilclient_id paramètre dans toutes les requêtes d'authentification./commun au lieu de cela, mais conservez cette valeur pour les URL de consentement d'administrateur.Choisir le bon point de terminaison d'autorité Microsoft
L'URL d'autorité que vous utilisez dans vos requêtes OAuth détermine quels types de comptes Microsoft peuvent s'authentifier et quels jetons vous recevez. Une erreur à ce niveau entraîne des échecs silencieux où certains utilisateurs ne peuvent pas du tout s'authentifier.
| URL d'autorité | Accepte | Cas d'utilisation | Mises en garde |
|---|---|---|---|
| /communLa plupart des SaaS | Comptes Microsoft Entra (professionnels/scolaires) et comptes Microsoft personnels (Outlook.com, Hotmail, Live) | Logiciel en tant que service multi-locataire desservant tous les utilisateurs Microsoft. Un seul point d'accès gère l'ensemble de votre base d'utilisateurs. | Les jetons sont émis par le locataire d'accueil de chaque utilisateur, pas par le vôtre. La validation des jetons doit utiliser l'émetteur spécifique au locataire ou accepter plusieurs émetteurs. Impossible d'appliquer les stratégies d'accès conditionnel. |
| /organisations | Comptes Microsoft Entra ID uniquement (professionnels/scolaires). Aucun compte Microsoft personnel. | Logiciel SaaS B2B ciblant uniquement les clients d'entreprise, jamais les utilisateurs grand public d'Outlook.com. | Les utilisateurs ayant des comptes Microsoft personnels recevront une erreur. Validation de jeton plus simple (modèle d'émetteur unique acceptable). |
| consommateurs | Comptes Microsoft personnels uniquement (Outlook.com, Hotmail, Live). | Applications grand public ciblant les boîtes de réception personnelles. Rare pour les SaaS B2B. | Les comptes Microsoft 365 d'entreprise sont rejetés. Inutile pour une offre SaaS destinée aux utilisateurs professionnels. |
| /{identifiant-du-locataire} | Comptes dans un client Microsoft Entra spécifique uniquement. | Outils internes à locataire unique (application de votre propre entreprise). Flux de consentement administrateur ciblant un locataire spécifique. Également utilisé dans le modèle d'URL de redirection du consentement administrateur. | Chaque autre utilisateur du locataire est rejeté. Approprié uniquement pour les applications internes ou lorsque l'on verrouille délibérément un seul locataire client. |
/commun point de terminaison, le Tss la revendication (issuer) dans le JWT sera https://login.microsoftonline.com/{tenantId}/v2.0 où {tenantId} varie par utilisateur. Configurez votre bibliothèque de validation JWT pour accepter n'importe quel émetteur correspondant https://login.microsoftonline.com/{tenantId}/v2.0 plutôt qu'une chaîne d'émetteur fixe.Microsoft Graph Mail Scopes : Répartition Granulaire
Microsoft Graph utilise des étendues d'autorisation pour contrôler ce que votre application peut faire. Demander trop d'étendues augmente les frictions sur l'écran de consentement et réduit la conversion. En demander trop peu entraîne des erreurs d'exécution. Voici toutes les étendues de courrier que vous devez connaître.
| Portée | Type | Ce qu'il permet | Consentement de l'administrateur ? |
|---|---|---|---|
| Mail.Read | Délégué | Lire tous les messages dans la boîte aux lettres de l'utilisateur authentifié. Comprend les en-têtes, le corps, les pièces jointes. Lecture seule - ne peut pas modifier ni envoyer. | Utilisateur |
| Mail.ReadBasic | Délégué | Lire les propriétés limitées du message : sujet, expéditeur, destinataires, date. Impossible de lire le corps du message ou les pièces jointes. Utile pour la liste d'e-mails légère sans accès au contenu complet. | Utilisateur |
| Mail.ReadWrite | Délégué | Lire et modifier tous les messages. Inclut la création, la mise à jour et la suppression de messages et de dossiers. Sur-ensemble de Mail.Read – ne demandez pas les deux. | Utilisateur |
| Mail.Send | Délégué | Envoyer des e-mails en tant qu’utilisateur authentifié. Requis même si vous disposez également de Mail.ReadWrite - l’envoi est une autorisation distincte dans Microsoft Graph. | Utilisateur |
| Mail.Recharge.Partagé | Délégué | Lire les e-mails dans les boîtes aux lettres partagées ou les boîtes aux lettres d'autres utilisateurs auxquels l'utilisateur authentifié a été autorisé à accéder. Pas pour lire la boîte aux lettres de l'utilisateur lui-même. | Utilisateur |
| Mail.ReadWrite.Shared | Délégué | Lire et modifier les courriels dans les boîtes aux lettres partagées auxquelles l'utilisateur a accès. | Utilisateur |
| Courriel.Envoyer.Partager | Délégué | Envoyer des e-mails à partir de boîtes aux lettres partagées ou "envoyer au nom de" un autre utilisateur (si cet utilisateur a accordé l'accès). | Utilisateur |
| accès_hors_ligne | Délégué | Demande à Microsoft d'émettre un jeton de mise à jour. Sans cela, vous ne recevez qu'un jeton d'accès de courte durée, sans possibilité de le renouveler. Toujours requis pour les applications SaaS. | Utilisateur |
| openid | Délégué | Retourne un jeton d'identification avec les informations d'identité de base de l'utilisateur. Nécessaire si vous souhaitez savoir qui s'est authentifié sans effectuer d'appel API /me distinct. | Utilisateur |
| profil | Délégué | Ajoute les revendications name et preferred_username au jeton d'identification. Généralement inclus avec openid. | Utilisateur |
| Mail.Lire (App) | Application | Lire tous les e-mails dans toutes les boîtes aux lettres du locataire sans interaction de l'utilisateur. Utilisé par les services démons. Nécessite le consentement de l'administrateur du locataire. | Administrateur requis |
| Mail.ReadWrite (Application) | Application | Lire et écrire tous les e-mails dans toutes les boîtes aux lettres des locataires. Permission très large. Uniquement pour les outils internes de confiance avec l'approbation explicite de l'administrateur du locataire. | Administrateur requis |
scope=Mail.Readaccès hors ligneopenidprofil
scope=Mail.ReadWriteMail.Sendoffline_accessopenidprofile
Autorisations déléguées vs autorisations d'application : Quand utiliser chacune
Microsoft Graph utilise deux modèles d'autorisations fondamentalement différents. La plupart des développeurs SaaS optent par défaut pour le mauvais, ce qui entraîne des exigences inutiles de consentement administrateur et une expérience utilisateur dégradée. Voici exactement quand utiliser chacun.
Code d'authentification + PKCE : exemples cURL étape par étape
Voici le flux d'autorisation OAuth 2.0 avec PKCE complet de Microsoft Graph, de la génération du code verifier à l'échange des jetons. Ce sont des exemples de qualité de production que vous pouvez adapter directement à votre stack.
import système, base64, hashlib
# 1. Générer un code_verifier (43 à 128 caractères, codage Base64 compatible URL)
code_verifier = base64.urlsafe_b64encode(
os.urandom(32)
).décoder('utf-8').enlever les espaces de fin('=')
# 2. Générer code_challenge = BASE64URL(SHA256(code_verifier))
défi_code = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encoder('utf-8')).résumé()
).décoder('utf-8').enlever les espaces de fin('=')
# Enregistrez la valeur de « code_verifier » dans la session — vous en aurez besoin à l'étape 4
# Envoyer le code_challenge dans l'URL d'autorisationcode - demande un code d'autorisationaccès_hors_ligne pour les jetons de rafraîchissement.S256 - toujours utiliser SHA-256, jamais en clair# Générer l'URL d'autorisation (format optimisé pour la lisibilité)
URL_AUTH="https://login.microsoftonline.com/common/oauth2/v2.0/authorize
?client_id=VOTRE_CLIENT_ID
&type_de_réponse=code
&redirect;_uri=https://3aapp.com/3aauth/3ams/3acb
&scope;=Mail.ReadWriteMail.Sendoffline_access
&state=VALEUR_ETAT_ALEATOIRE
&défi_code=VOTRE_DÉFI_CODE
&code_challenge_method=S256"
# Rediriger l'utilisateur vers $AUTH_URL
# : Microsoft gère la connexion, l'authentification à plusieurs facteurs (MFA) et l'écran de consentement
# En cas de réussite : redirect_uri?code=AUTH_CODE&state;=...code paramètre de requête. Valider le état Le paramètre correspond à ce que vous avez envoyé. Le code expire dans 10 minutes - échangez-le immédiatement à l'étape 4.Code d'autorisation d'échange # pour les jetons
curl -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token" \
-H "Content-Type : application/x-www-form-urlencoded" \
-d "client_id=VOTRE_CLIENT_ID" \
-d "client_secret=VOTRE_CLIENT_SECRET" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE_FROM_CALLBACK" \
-d "redirect_uri=https://app.com/auth/ms/cb" \
-d "code_verifier=VOTRE_CODE_VERIFICATEUR" \
-d "scope=Mail.ReadWrite Mail.Send offline_access"{
"type_de_jeton": "Porteur",
"portée": "Mail.ReadWrite Mail.Send offline_access",
"expire_dans": 3600,
"jeton_d'accès": "eyJ0eXAiOiJKV1Qi...",
"jeton_rafraîchissement": "0.ARoAi7W...",
"jeton_identifiant": "eyJ0eXAi..."
}Gestion des jetons de rafraîchissement : rotation, expiration et accès conditionnel
Les jetons d’actualisation Microsoft Graph sont de longue durée mais pas permanents. Plusieurs conditions peuvent les invalider silencieusement. Comprendre ces cas limites est ce qui distingue une intégration Microsoft OAuth de qualité de production d’une intégration qui échoue aléatoirement pour les utilisateurs d’entreprise.
grant_invalide En cas d'erreur, inviter à une nouvelle authentification.grant_invalide erreur.grant_invalide. Ceci est un comportement attendu - gérez-le en marquant le compte lié comme nécessitant une ré-autorisation.# Actualiser le jeton d'accès à l'aide du jeton d'actualisation enregistré
curl -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token" \
-H "Content-Type : application/x-www-form-urlencoded" \
-d "client_id=VOTRE_CLIENT_ID" \
-d "client_secret=VOTRE_CLIENT_SECRET" \
-d "grant_type=refresh_token" \
-d "refresh_token=TOKEN_DE_RAFFRAÎCHISSEMENT_ENREGISTRÉ" \
-d "scope=Mail.ReadWrite Mail.Send offline_access"
# Vérifiez TOUJOURS si la réponse contient un nouveau refresh_token.
# Si présent, remplacez immédiatement celui qui est stocké.
# Si vous obtenez une erreur « invalid_grant », demandez à l'utilisateur de se réauthentifier.Erreurs courantes AADSTS décodées
Les erreurs Microsoft Graph OAuth suivent un schéma cohérent de code d'erreur AADSTS. Voici les plus courantes que vous rencontrerez lors du développement et de la production, avec leurs causes profondes exactes et leurs correctifs.
| Code d'erreur | Ce que cela signifie | Cause principale et correction |
|---|---|---|
| AADSTS65001 | Le consentement n'a pas été accordé pour une ou plusieurs des portées demandées | L'utilisateur n'a pas consenti aux étendues de votre application, ou un administrateur de locataire a bloqué le consentement de l'utilisateur pour votre application. Correction : Inclure consentement dans votre URL d'autorisation pour forcer un écran de consentement réinitialisé, ou envoyer l'URL de consentement de l'administrateur à l'administrateur de locataire.Ajoutez prompt=consentement ou demandez le consentement de l'administrateur |
| AADSTS50011 | Incompatibilité de l'URI de redirection | Le uri_de_redirection Dans votre requête, l'URI de redirection ne correspond exactement à aucun URI de redirection enregistré dans votre inscription d'application Entra. Même une différence de barre oblique finale suffit. Correction : Copiez l'URI exact de votre inscription d'application Entra et utilisez-le tel quel.Correction : correspondance exacte de l'URI dans l'enregistrement d'application Entra |
| AADSTS700016 | Application introuvable dans le tenant | Le client_id n'existe pas dans le locataire auquel vous vous authentifiez. Courant lorsque vous utilisez une autorité spécifique à un locataire (/{identifiant-du-locataire}) pour une application multi-locataire. Correction : Utiliser /commun ou /organisations autorité pour les applications multi-locataires.Correction : passer à l'autorité /common ou /organizations |
| AADSTS90099 | Application non autorisée dans ce locataire (consentement requis) | L'application existe mais n'a pas été consentie dans le locataire de l'utilisateur. Diffère de AADSTS65001 en ce que toute l'application est bloquée, et pas seulement des étendues spécifiques. Correction : Envoyez l'URL de consentement de l'administrateur à l'administrateur informatique du client. Correction : URL de consentement admin vers l'admin du client |
| AADSTS70011 | Le don fourni est invalide ou expiré | Le jeton d'actualisation ou le code d'autorisation a expiré ou a été révoqué. Les codes d'autorisation expirent dans les 10 minutes. Les jetons d'actualisation expirent après 90 jours d'inactivité ou après révocation par l'administrateur. Correction : Invitez l'utilisateur à se réauthentifier depuis le début du flux OAuth. Correction : ré-authentification complète du prompt |
| AADSTS50076 | L'authentification multifacteur est requise par la stratégie d'accès conditionnel | Le locataire de l'utilisateur nécessite l'authentification multifacteur pour votre application. C'est une décision côté client appliquée par l'administrateur du locataire. Votre application ne peut pas la contourner. L'utilisateur doit terminer l'MFA. Si vous utilisez le flux de code d'autorisation, Microsoft affichera automatiquement l'invite MFA dans le navigateur. Des problèmes surviennent dans les flux automatisés (informations d'identification client) qui ne peuvent pas terminer l'MFA. Attendu : l'utilisateur doit effectuer l'authentification multifacteur |
| AADSTS50020 | Le compte utilisateur du fournisseur d'identité externe n'existe pas dans le locataire | L'utilisateur essaie de s'authentifier avec un compte Microsoft personnel dans un répertoire qui n'autorise que les comptes professionnels, ou vice versa. Correction : Vérifiez votre point de terminaison d'autorité - si vous utilisez /organisations, les comptes personnels ne peuvent pas s'authentifier. Basculez vers /commun si vous avez besoin des deux.Corriger : changer l'autorité à /common |
| AADSTS53003 | Accès bloqué par la stratégie d'accès conditionnel | La stratégie d'accès conditionnel du locataire a complètement bloqué cette tentative d'authentification (par exemple, pays bloqué, appareil non géré, application bloquée). Il s'agit d'une décision côté client. Vous ne pouvez pas la substituer. Affichez l'erreur à l'utilisateur et conseillez-lui de contacter son administrateur informatique. Côté client : conseillez à l'utilisateur de contacter l'administrateur informatique |
Évitez 5 semaines de plomberie OAuth avec Unipile
Tout dans ce guide - enregistrement d'applications Entra, points de terminaison d'autorité, sélection des étendues, PKCE, rotation des jetons, gestion des erreurs AADSTS - représente du temps d'ingénierie qui n'avance pas votre produit. Unipile gère l'intégralité de la pile OAuth Microsoft Graph en tant que service géré, ainsi votre équipe écrit un appel d'API au lieu de 500 lignes de code OAuth.
import demandes
URL_API_UNIPILE = "https://apiXXX.unipile.com:XXX"
CLÉ_API_UNIPILE = "votre-api-clé"
# Étape 1 : Générer un lien d'authentification hébergé pour Microsoft
response = requests.poste(
"{UNIPILE_API_URL}/api/v1/hosted/accounts/link",
en-têtes={
"X-API-KEY": UNIPILE_API_KEY,
"Content-Type": "application/json"
},
json={
"type": "créer",
"fournisseurs": ["MICROSOFT"],
"api_url": UNIPILE_API_URL,
"expireLe": "2026-12-31T23:59:59Z",
# Facultatif : associer ce lien à un utilisateur spécifique
"nom": "id_utilisateur_123",
# (facultatif) : recevoir une notification lorsque le compte est associé
"url_de_notification": "https://app.yourproduct.com/webhooks/account-linked"
}
)
# Étape 2 : Redirigez votre utilisateur vers cette URL
hébergé_url_authentification = réponse.json()["url"]
Exemple # : https://account.unipile.com/[encoded-token]
# Gestion des piles : redirection Entra, écran de consentement, PKCE,
Échange de jetons #, actualisation du stockage des jetons, gestion de la portée
# Étape 3 : Une fois l'authentification effectuée, utilisez l'API de messagerie d'Unipile pour lire/envoyer des e-mails
courriels = demandes.obtenir(
f"{UNIPILE_API_URL}/api/v1/emails",
en-têtes={"X-API-KEY": {UNIPILE_API_KEY},
params={"account_id": "identifiant-compte-lie"}
)Questions fréquemment posées
Les questions les plus fréquentes sur l'authentification OAuth de Microsoft Graph pour l'intégration d'e-mails, de la sélection des étendues à la gestion du cycle de vie des jetons en passant par les flux de consentement d'entreprise.
/commun point de terminaison d'autorité, qu'une seule inscription d'application Microsoft Entra gère l'authentification des comptes Outlook.com personnels et des comptes professionnels/scolaires Microsoft 365. La clé est de sélectionner "Comptes dans n'importe quel répertoire d'organisation et comptes Microsoft personnels" lors de l'inscription de votre application dans le portail Azure.grant_invalide Erreur. Gérez ceci avec élégance : marquez le compte lié comme nécessitant une réauthentification et affichez une invite de réauthentification claire dans votre produit. C'est un comportement attendu - une décision côté client échappant à votre contrôle.Mail.Read, Mail.ReadWrite, ou encore Mail.Send sont des scopes de consentement utilisateur - les utilisateurs individuels peuvent les approuver lors du flux OAuth. Le consentement de l'administrateur n'est requis que pour les permissions d'application ou les scopes à privilèges élevés comme `Utilisateur.Lire.Tous`. Certains locataires d'entreprise configurent des stratégies qui bloquent tout consentement d'application tierce - c'est une décision côté client.grant_invalide erreurs et remplacer les anciens jetons de rafraîchissement par le nouveau retourné dans chaque réponse de jeton.consentement vers votre URL d'autorisation pour forcer un nouvel écran de consentement. AADSTS90099L'application entière n'a pas été autorisée dans ce locataire. L'administrateur du locataire doit pré-approuver votre application. Envoyez l'URL de consentement de l'administrateur à l'administrateur informatique du client. Les deux erreurs sont courantes dans les scénarios d'entreprise où les locataires restreignent le consentement des utilisateurs.Mail.ReadWrite et Mail.Send dans le même portée de chaîne. Notez que Mail.ReadWrite et Mail.Send sont des étendues séparées - avoir un accès en lecture/écriture ne vous accorde pas automatiquement l'autorisation d'envoi. Incluez toujours accès_hors_ligne pour vous assurer de recevoir un jeton de rafraîchissement. Voir le Page de l'API de messagerie pour les détails de mise en œuvre.