Exchange Online POP and IMAP OAuth 2.0 Client Credentials Flow
Hi All,
OAuth 2 Authentication for POP and IMAP was announced already back in June 2022 at the Exchange Team Blog.
Announcing OAuth 2.0 Client Credentials Flow support for POP and IMAP protocols in Exchange Online
https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-oauth-2-0-client-credentials-flow-support-for-pop-and/ba-p/3562963
https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-oauth-2-0-client-credentials-flow-support-for-pop-and/ba-p/3562963
There is a pretty decent Step-by-step Guide here. But there are some steps missing - that's why i have created a more detailed Guide.
Authenticate an IMAP, POP or SMTP connection using OAuth
https://docs.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-imap-and-pop-connections
As a personal Opinion: I don't like this POP/IMAP approach. If you as a developer are able to change your existing Code for the Authentication and Token handling - you have already done 50% of the Job. It's easy to do the rest via Graph Calls - check out mit GitHub Repo for Examples of that https://github.com/BohrenAn/GitHub_PowerShellScripts/blob/main/ExchangeOnline/GraphAPI/ExOGraphAPI.ps1
Create the App Registration in Azure AD
Add the Permissions for the App:
Office 365 Exchange Online
- IMAP.AccessAsApp
- POP.AccessAsApp
How do you select these Permissions?
It's a little bit tricky. Instead of Microsoft Graph select the "APIs my organization uses" and search for "Office 365 Exchange Online"
Then select "Application permissions" and search for "POP" and "IMAP"
Now you need to create the Service Principal in Exchange Online. And here is another tricky part.
What do they refer to with ServiceId? It is the ObjectID of your Azure AD Application in the Enterprise Application.
New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]
I've made that simpler with thist Microsoft Graph Call
###############################################################################
# Get AzureAD Application with Microsoft.Graph PowerShell
###############################################################################
Connect-MgGraph -Scopes 'Application.Read.All'
$ServicePrincipalDetails = Get-MgServicePrincipal -Filter "DisplayName eq 'DemoEXO-POP3-IMAP'"
$ServicePrincipalDetails
# Get AzureAD Application with Microsoft.Graph PowerShell
###############################################################################
Connect-MgGraph -Scopes 'Application.Read.All'
$ServicePrincipalDetails = Get-MgServicePrincipal -Filter "DisplayName eq 'DemoEXO-POP3-IMAP'"
$ServicePrincipalDetails
We now can create the Service Principal with the Object from the Microsoft Graph call
###############################################################################
# Create Exchange Service Principal
###############################################################################
Connect-ExchangeOnline
New-ServicePrincipal -AppId $ServicePrincipalDetails.AppId -ServiceId $ServicePrincipalDetails.Id -DisplayName "EXO Serviceprincipal $($ServicePrincipalDetails.Displayname)"
# Create Exchange Service Principal
###############################################################################
Connect-ExchangeOnline
New-ServicePrincipal -AppId $ServicePrincipalDetails.AppId -ServiceId $ServicePrincipalDetails.Id -DisplayName "EXO Serviceprincipal $($ServicePrincipalDetails.Displayname)"
Now you need to check if POP or IMAP is enabled on the Account
###############################################################################
# CAS Mailbox
###############################################################################
Get-CASMailbox -Identity m.muster@icewolf.ch | fl imap*
Set-CASMailbox -Identity m.muster@icewolf.ch -PopEnabled $true -ImapEnabled $true
# CAS Mailbox
###############################################################################
Get-CASMailbox -Identity m.muster@icewolf.ch | fl imap*
Set-CASMailbox -Identity m.muster@icewolf.ch -PopEnabled $true -ImapEnabled $true
You also need to give "Full Access" Permission to the Service Principal of the App
###############################################################################
#Full Access
###############################################################################
$Mailbox = "m.muster@icewolf.ch"
$SericePrincipal = "EXO Serviceprincipal DemoEXO-POP3-IMAP"
Add-MailboxPermission -Identity $Mailbox -User $SericePrincipal -AccessRights FullAccess -AutoMapping $false
#Full Access
###############################################################################
$Mailbox = "m.muster@icewolf.ch"
$SericePrincipal = "EXO Serviceprincipal DemoEXO-POP3-IMAP"
Add-MailboxPermission -Identity $Mailbox -User $SericePrincipal -AccessRights FullAccess -AutoMapping $false
Check Full Access Permissions
$Mailbox = "m.muster@icewolf.ch"
Get-MailboxPermission -Identity $Mailbox | Where-Object { ($_.AccessRights -eq "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") } | ft -AutoSize
Get-MailboxPermission -Identity $Mailbox | Where-Object { ($_.AccessRights -eq "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") } | ft -AutoSize
Now you can check with this tool
OAuth2 IMAP Test Tool
https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1
https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1
###############################################################################
# Test Access
###############################################################################
Clear-MsalTokenCache
$AppID = "3bf0cf36-87bf-47a9-927b-0ef9df7cf146"
$TenantID = "icewolfch.onmicrosoft.com"
$ClientSecret = "YourClientSecret"
$Scope = "https://outlook.office.com/IMAP.AccessAsUser.All"
.\Get-IMAPAccessToken.ps1 -tenantID $TenantID -clientId $AppID -clientsecret $ClientSecret -targetMailbox "m.muster@icewolf.ch"
# Test Access
###############################################################################
Clear-MsalTokenCache
$AppID = "3bf0cf36-87bf-47a9-927b-0ef9df7cf146"
$TenantID = "icewolfch.onmicrosoft.com"
$ClientSecret = "YourClientSecret"
$Scope = "https://outlook.office.com/IMAP.AccessAsUser.All"
.\Get-IMAPAccessToken.ps1 -tenantID $TenantID -clientId $AppID -clientsecret $ClientSecret -targetMailbox "m.muster@icewolf.ch"
That's how it looks like if your IMAP Protocol in Get-CASMailbox is not enabled (And it takes a while 30-60 Minutes) after the Change to become active.
Here we go
You can also use Remote Connectivity Analyzer to verify the IMAP Access.
Microsoft Remote Connectivity Analyzer
Check out also other ways of Testing your IMAP OAuth2 Flow
Regards
Andres Bohren