Du kennst das Spiel: Die Abschaltung der Basic Authentication zwingt uns alle zum Handeln. Dein DMS, Ticketsystem oder Archiv soll endlich per OAuth2 auf Exchange Online zugreifen.
In Azure sieht alles grün aus, das Token kommt, aber der Zugriff knallt. Warum das passiert und wie du den „LogonDenied“ Fehler fixst.

Die Umstellung auf den sogenannten „Client Credentials Flow“ ist eigentlich Standard. App registrieren, Rechte geben, fertig. Aber gerade bei Legacy-Protokollen wie IMAP lauert ein Fehlerteufel, der dich Stunden kosten kann.
Szenario: Alles grün, trotzdem „Zugriff verweigert“
Du hast deine Hausaufgaben gemacht: Deine App ist sauber in Azure AD (Entra ID) registriert. Du nutzt für deinen Hintergrunddienst – sei es ein DMS-Importer, ein Ticketsystem-Scanner oder eine Archivierungslösung – etablierte Bibliotheken wie MailBee, Aspose oder Chilkat.
Der Code steht, das OAuth-Token wird erfolgreich vom Azure-Endpunkt abgerufen. Das Client-Secret stimmt also. Doch im Moment der Wahrheit, wenn sich die Anwendung via IMAP am Postfach anmelden will, knallt es.
Im Logfile starrt dich eine Fehlermeldung an, die dich auf die falsche Fährte lockt: BadCredentials.
Exception: MailBeeImapLoginBadCredentialsException
Response: MBN00000002 NO AUTHENTICATE failed.
Error="AuthFailed:LogonDenied-None-OAuthLog:AuthExc_Auth Failed. [...] User:XXXXXXXX@..."
Lass dich von „Bad Credentials“ nicht täuschen. Dein Passwort (Secret) ist korrekt. Der entscheidende Hinweis versteckt sich im Detail: LogonDenied.
Ursache: Missverständnis zwischen Azure und Exchange Online
Warum passiert das? Du hast doch in Azure die API-Permissions gesetzt, oder? Das Problem liegt in der strikten Trennung der Zuständigkeiten innerhalb von Microsoft 365. Du bist hier Opfer des Unterschieds zwischen Authentifizierung und Autorisierung geworden.
Stell dir das wie vor einem exklusiven Club vor:
- Azure AD (Entra ID) ist der Türsteher (Authentication): Er prüft den Ausweis deiner App (Client ID & Secret). Ist der Ausweis echt? Ja. Ergebnis: Der Türsteher drückt deiner App einen Stempel auf die Hand (das Access Token) und lässt sie ins Gebäude. Azure hat seinen Job erledigt.
- Exchange Online ist der Betreiber des VIP-Bereichs (Authorization): Deine App steht nun mit dem Stempel im Flur und will in den VIP-Bereich (das konkrete Postfach). Der Betreiber schaut sich den Stempel an, zuckt aber mit den Schultern. Er weiß zwar, wer die App ist, aber auf seiner Gästeliste für diesen speziellen VIP-Tisch steht sie nicht. Ergebnis: LogonDenied.
Der technische Hintergrund: Beim Client Credentials Flow (App-Only Zugriff) gibt es keinen Benutzerkontext. Exchange Online weiß standardmäßig schlichtweg nicht, dass dieser abstrakte „Service Principal“ aus Azure berechtigt sein soll, die E-Mails von docscan@... zu lesen.
Anders als bei der modernen Graph API, wo Rechte oft globaler greifen, ist die alte IMAP-Schnittstelle in Exchange konservativ. Sie verlangt eine explizite Verknüpfung: „Dieser Service Principal darf in dieses Postfach schauen.“
Und genau diese Verknüpfung fehlt – selbst wenn du in Azure „FullAccess“ angehakt hast. Azure kann dieses Recht nicht bis in den Exchange-Store „durchdrücken“. Dieser Link muss manuell im Backend von Exchange gesetzt werden. Und das geht nur über die PowerShell.
Hier sind die drei Stolpersteine, die du jetzt prüfen musst:
1: Die Graph-Falle (oder: Warum Modern nicht immer klappt)
Microsofts Marschrichtung ist klar: Alles soll über die Microsoft Graph API laufen. Wenn du also eine neue App registrierst, landest du automatisch dort. Das Problem: Deine Legacy-Anwendung spricht IMAP (RFC 3501), nicht REST/JSON.
Wenn du in der Graph API Berechtigungen wie Mail.Read vergibst, erhältst du zwar ein gültiges Token – aber dieses Token ist für die Graph-Schnittstelle gedacht. Der IMAP-Endpunkt (outlook.office365.com) weist dieses Token oft ab oder akzeptiert es nur im delegierten Kontext (User-Login), aber nicht für Hintergrunddienste (App-Only).
Die Lösung: Die versteckte Legacy-API Du benötigst zwingend die API „Office 365 Exchange Online“. Microsoft hat diese jedoch in der Standard-Auswahlliste ausgeblendet, um Entwickler zu Graph zu drängen. Wenn du einfach nach dem Namen suchst, findest du sie oft gar nicht.
So kommst du trotzdem dran (der „Pro-Trick“):
- Gehe zu App-Registrierungen -> Deine App -> API-Berechtigungen.
- Klick auf „Berechtigung hinzufügen“.
- Wechsle oben auf den Reiter „Von meiner Organisation verwendete APIs“.
- Ignoriere die Namenssuche! Tippe stattdessen direkt die interne GUID von Exchange Online ein:
00000002-0000-0ff1-ce00-000000000000 - Klick auf den Treffer Office 365 Exchange Online.
- Wähle Anwendungsberechtigungen (Application permissions) – nicht „Delegierte Berechtigungen“!
- Such nach
IMAPund setz den Haken beiIMAP.AccessAsApp. - Lebenswichtig: Klick danach oben auf den Button „Administratorzustimmung erteilen“. Ohne diesen Klick ist der Haken wertlos.




2: Die falsche Objekt-ID
Dies ist der absolute Klassiker, an dem fast alle manuellen PowerShell-Versuche scheitern. Wenn wir gleich das Skript nutzen, um Exchange und Azure zu verheiraten, fragt das Cmdlet nach der ServiceId (Objekt-ID).
Das Gemeine: Azure zeigt dir an zwei verschiedenen Orten eine „Objekt-ID“ für deine App an – und es sind zwei verschiedene Nummern!
- Die ID der App-Registrierung (App Registration): Das ist der „Bauplan“ deiner App. Diese ID findest du unter „App-Registrierungen“.
- Für Exchange ist diese ID nutzlos!!!
- Die ID der Unternehmensanwendung (Enterprise Application): Das ist der sogenannte „Service Principal“ – die konkrete Instanz der App, die in deinem Tenant läuft.
- Genau diese ID braucht Exchange!!!
Der Fehler: Nimmst du die ID aus der App-Registrierung, wirft PowerShell den Fehler: AADServicePrincipalNotFound. Exchange sagt quasi: „Ich kenne diesen Typen nicht.“

So machst du es richtig:
- Verlasse den Bereich „App-Registrierungen“.
- Suche im Azure Portal oben nach „Unternehmensanwendungen“ (Enterprise Applications).
- Suche dort nach deiner App (über die Client-ID oder den Namen).
- Klick sie an und kopiere dir die Objekt-ID aus der Übersicht. (Pro-Tipp: Diese ID ist anders als die, die du bisher genutzt hast!)


3: Der Faktor Zeit & das Cache-Problem (Die Geduldsfalle)
Das ist der Moment, an dem Admins an ihrem Verstand zweifeln. Du hast die API korrigiert, die richtige ID gefunden und das PowerShell-Skript ausgeführt. Alles meldet „Success“.
Du startest den Abruf und … LogonDenied. Immer noch.
Bevor du jetzt alles wieder abreißt: Das ist normal. Hier spielen zwei Mechanismen gegen deine Ungeduld:
- Exchange Replikation: Wenn du
Add-MailboxPermissionausführst, muss diese Info erst durch die Microsoft-Cloud repliziert werden. Das dauert offiziell bis zu 60 Minuten. In der Praxis meist 5 bis 15 Minuten. - Das Access Token Caching (Der Endgegner): Das ist der wichtigere Punkt. Deine Anwendung holt sich ein OAuth-Token von Azure. Dieses Token ist 1 Stunde lang gültig. Hat sich deine App vor deinem Fix ein Token geholt, steht in diesem Token noch nicht drin, dass es auf das Postfach darf. Die App versucht es also die nächsten 50 Minuten stur mit dem alten, ungültigen „Ticket“.
Die Lösung: Starte den Windows-Dienst deiner Anwendung (Dienst) einmal komplett neu. Das zwingt die App, das alte Token wegzuwerfen und ein frisches von Azure anzufordern – diesmal mit den korrekten Rechten. Danach: Hol dir einen Kaffee und gib Exchange 10 Minuten Zeit.
Die Lösung: Der PowerShell-Fix
Genug der Theorie. Damit Exchange den Zugriff erlaubt, musst du den in Azure erstellten Service Principal im Exchange bekannt machen und ihm Vollzugriff auf das Zielpostfach geben.
Schnapp dir deine Exchange Online PowerShell (als Admin) und die Objekt-ID aus den Unternehmensanwendungen (siehe #2), die du dir notiert hast:
Connect-ExchangeOnline
# --- KONFIGURATION ---
# Die Application (Client) ID (bleibt gleich)
$AppId = "DEINE-APP-CLIENT-ID"
# ACHTUNG: Hier die Objekt-ID aus den UNTERNEHMENSANWENDUNGEN rein!
$ServiceId = "DEINE-ENTERPRISE-APP-OBJECT-ID"
$Mailbox = "ziel-email@deine-domain.de"
$DisplayName = "Name deiner App"
# ---------------------
# 1. Service Principal in Exchange registrieren
# Falls er schon existiert, kommt ein Fehler - den kannst du ignorieren.
try {
New-ServicePrincipal -AppId $AppId -ServiceId $ServiceId -DisplayName $DisplayName -ErrorAction Stop
Write-Host "Service Principal registriert." -ForegroundColor Green
}
catch {
Write-Host "Info: $($_.Exception.Message)" -ForegroundColor Yellow
}
# 2. Zugriff auf das Postfach gewähren
# Das ist der entscheidende Schritt gegen "LogonDenied"
Add-MailboxPermission -Identity $Mailbox -User $ServiceId -AccessRights FullAccess
Write-Host "Fertig! Jetzt heißt es warten..."
Checkliste: Wenn es trotzdem nicht geht
Du hast das Skript fehlerfrei ausgeführt, startest deine Anwendung und siehst immer noch AUTHENTICATE failed? Keine Panik, prüf diese drei Punkte:
- Geduld ist Pflicht: Exchange arbeitet asynchron. Änderungen via
Add-MailboxPermissionbrauchen offiziell bis zu 60 Minuten Replikationszeit, bis sie auf allen Servern weltweit aktiv sind. In der Praxis klappt es meist nach 15–20 Minuten. Hol dir einen Kaffee. - Dienst neustarten (Token-Cache)! Das ist der häufigste Grund für unnötiges Kopfzerbrechen. Deine Anwendung hat sich vermutlich vor 30 Minuten ein Access Token geholt. Dieses Token ist 1 Stunde gültig und darin fehlen die neuen Rechte noch. Solange die App das alte Token nutzt, bleibst du draußen. Starte den Windows-Dienst deiner App einmal komplett neu, um ein frisches Token zu erzwingen.
- Ist der User aktiviert? Auch wenn es eine Shared Mailbox ist: Für OAuth muss das Benutzerobjekt in Azure oft aktiviert sein (
AccountEnabled = $true), auch wenn sich kein Mensch interaktiv anmeldet. Prüfe, ob „Anmeldung blockieren“ auf dem User aktiv ist, und nimm es testweise raus.
Viel Erfolg beim Umstellen!
OAuth und Legacy-Protokolle sind eine heikle Mischung, aber mit dem richtigen PowerShell-Handgriff bekommst du auch das stabil zum Laufen. Wenn du noch Fragen hast oder über einen anderen exotischen Fehlercode gestolpert bist, schreib es einfach in die Kommentare – wir lernen alle noch dazu.


Hinterlasse jetzt einen Kommentar